-
Notifications
You must be signed in to change notification settings - Fork 60
feat: Add Anthropic integration in HTTP transport #65
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
feat: Add Anthropic integration in HTTP transport #65
Conversation
Caution Review failedThe pull request is closed. Summary by CodeRabbit
Summary by CodeRabbit
WalkthroughThese changes introduce Anthropic API compatibility to the Bifrost HTTP transport layer. New files define request/response types and conversion logic between Anthropic and Bifrost schemas. An Anthropic router is added, handling Changes
Sequence Diagram(s)sequenceDiagram
participant Client
participant AnthropicRouter
participant BifrostClient
participant CoreProvider
Client->>AnthropicRouter: POST /anthropic/v1/messages (AnthropicMessageRequest)
AnthropicRouter->>AnthropicRouter: Convert AnthropicMessageRequest to BifrostRequest
AnthropicRouter->>BifrostClient: ChatCompletionRequest(BifrostRequest)
BifrostClient->>CoreProvider: Process request
CoreProvider-->>BifrostClient: BifrostResponse
BifrostClient-->>AnthropicRouter: BifrostResponse
AnthropicRouter->>AnthropicRouter: Convert BifrostResponse to AnthropicMessageResponse
AnthropicRouter-->>Client: 200 OK (AnthropicMessageResponse)
Poem
📜 Recent review detailsConfiguration used: CodeRabbit UI 📒 Files selected for processing (7)
✨ Finishing Touches
🪧 TipsChatThere are 3 ways to chat with CodeRabbit:
SupportNeed 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)
Other keywords and placeholders
CodeRabbit Configuration File (
|
This stack of pull requests is managed by Graphite. Learn more about stacking. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Actionable comments posted: 9
📜 Review details
Configuration used: CodeRabbit UI
Review profile: ASSERTIVE
Plan: Pro
📒 Files selected for processing (4)
core/providers/anthropic.go
(1 hunks)transports/bifrost-http/integrations/anthropic/router.go
(1 hunks)transports/bifrost-http/integrations/anthropic/types.go
(1 hunks)transports/bifrost-http/main.go
(2 hunks)
🧰 Additional context used
🧬 Code Graph Analysis (2)
transports/bifrost-http/main.go (1)
transports/bifrost-http/integrations/anthropic/router.go (1)
NewAnthropicRouter
(18-20)
transports/bifrost-http/integrations/anthropic/router.go (3)
core/bifrost.go (2)
Bifrost
(39-51)ChatCompletionRequest
(24-24)transports/bifrost-http/integrations/anthropic/types.go (2)
AnthropicMessageRequest
(90-102)DeriveAnthropicFromBifrostResponse
(314-377)transports/bifrost-http/lib/ctx.go (1)
ConvertToBifrostContext
(43-73)
🔇 Additional comments (5)
transports/bifrost-http/main.go (2)
32-33
: Import side-effect looks goodAnthropic integration is cleanly added to the imports; no issues spotted.
184-185
: Router registration order OK but watch for route collisionsAdding
anthropic.NewAnthropicRouter
after OpenAI/GenAI is fine; routes are namespaced (/anthropic/...
) so no collisions expected.core/providers/anthropic.go (1)
486-488
: Nice consolidation of switch casesThe
fallthrough
correctly deduplicates logic for"function"
vs"tool"
types. 👍transports/bifrost-http/integrations/anthropic/router.go (2)
1-10
: LGTM! Clean package structure and appropriate imports.The package declaration and imports are well-organized and include all necessary dependencies for the Anthropic integration.
12-25
: LGTM! Well-structured router with clean separation of concerns.The AnthropicRouter struct, constructor, and route registration follow Go best practices and properly encapsulate the Bifrost client dependency.
70efb6c
to
9bc0828
Compare
dde6b39
to
2cbc913
Compare
There was a problem hiding this 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 (4)
transports/bifrost-http/integrations/anthropic/router.go (2)
34-35
: Don’t ignore JSON-marshal errors
Silently discardingjson.Marshal
failures makes diagnosis impossible. At minimum, log and fall back to 500.
40-42
: Inconsistent error format (plain text vs JSON)
The 400 branch returns a plain string whereas all other branches return JSON.transports/bifrost-http/integrations/anthropic/types.go (2)
283-292
: Swallowed marshal errors hide malformed inputs
jsonifyInput
returns"{}"
on marshal failure, discarding information that could aid debugging and corrupting arguments.
104-112
:⚠️ Potential issue
Stream
flag is dropped – streaming requests executed in non-streaming mode
AnthropicMessageRequest.Stream
is parsed but never propagated toschemas.BifrostRequest
, breaking the contract for callers expecting SSE.Input: schemas.RequestInput{ ChatCompletionInput: &[]schemas.BifrostMessage{}, }, + Stream: r.Stream, }
📜 Review details
Configuration used: CodeRabbit UI
Review profile: ASSERTIVE
Plan: Pro
📒 Files selected for processing (4)
core/providers/anthropic.go
(1 hunks)transports/bifrost-http/integrations/anthropic/router.go
(1 hunks)transports/bifrost-http/integrations/anthropic/types.go
(1 hunks)transports/bifrost-http/main.go
(2 hunks)
🧰 Additional context used
🧠 Learnings (2)
core/providers/anthropic.go (1)
Learnt from: Pratham-Mishra04
PR: maximhq/bifrost#55
File: core/providers/anthropic.go:483-494
Timestamp: 2025-06-04T09:36:27.956Z
Learning: In the Anthropic provider (core/providers/anthropic.go), the user has confirmed through practical experience that the tool_choice parameter should always use an object format with a "type" field (e.g., {"type": "auto"}, {"type": "tool", "name": "function_name"}), even though the official documentation examples sometimes show "auto" as a direct string. The current implementation correctly handles all tool choice types with the object format.
transports/bifrost-http/integrations/anthropic/types.go (1)
Learnt from: Pratham-Mishra04
PR: maximhq/bifrost#55
File: core/providers/anthropic.go:483-494
Timestamp: 2025-06-04T09:36:27.956Z
Learning: In the Anthropic provider (core/providers/anthropic.go), the user has confirmed through practical experience that the tool_choice parameter should always use an object format with a "type" field (e.g., {"type": "auto"}, {"type": "tool", "name": "function_name"}), even though the official documentation examples sometimes show "auto" as a direct string. The current implementation correctly handles all tool choice types with the object format.
🧬 Code Graph Analysis (2)
transports/bifrost-http/main.go (1)
transports/bifrost-http/integrations/anthropic/router.go (1)
NewAnthropicRouter
(18-20)
transports/bifrost-http/integrations/anthropic/types.go (3)
core/utils.go (1)
Ptr
(3-5)core/schemas/bifrost.go (21)
ToolChoiceTypeFunction
(126-126)ToolChoice
(137-140)BifrostRequest
(54-64)Anthropic
(36-36)RequestInput
(46-49)BifrostMessage
(143-152)ModelChatMessageRoleSystem
(25-25)ModelChatMessageRole
(20-20)ToolCall
(266-270)Function
(101-105)FunctionCall
(260-263)AssistantMessage
(166-171)ModelChatMessageRoleTool
(27-27)ToolMessage
(160-163)ModelParameters
(75-89)Tool
(108-112)FunctionParameters
(92-98)ToolChoiceType
(116-116)ToolChoiceFunction
(132-134)BifrostResponse
(184-194)LLMUsage
(197-203)core/providers/anthropic.go (1)
AnthropicToolChoice
(20-24)
🔇 Additional comments (4)
transports/bifrost-http/main.go (2)
32-35
: Anthropic router import fits project layering – no action neededThe additional import is scoped to the HTTP transport layer and preserves the existing dependency direction. Good incremental extension.
184-185
: Router slice now includes Anthropic – LGTMThe new router is appended after OpenAI; ordering is non-critical because each registers unique paths. No further changes required.
core/providers/anthropic.go (1)
486-491
: Correct mapping offunction
→"tool"
keeps Anthropic happyUnifying
ToolChoiceTypeFunction
and"tool"
avoids the scenario where"function"
would reach the wire even though Anthropic only accepts"tool"
. Implementation is concise and usesfallthrough
properly.transports/bifrost-http/integrations/anthropic/router.go (1)
47-51
:⚠️ Potential issueNil-pointer panic possible when context conversion fails
lib.ConvertToBifrostContext
can returnnil
(see main.go error handling) yet*bifrostCtx
is dereferenced unconditionally. A malformed or cancelled request would crash the handler.bifrostCtx := lib.ConvertToBifrostContext(ctx) - result, err := a.client.ChatCompletionRequest(*bifrostCtx, bifrostReq) + if bifrostCtx == nil { + ctx.SetStatusCode(fasthttp.StatusInternalServerError) + ctx.SetContentType("application/json") + _ = json.NewEncoder(ctx).Encode(map[string]string{"error": "failed to convert context"}) + return + } + result, err := a.client.ChatCompletionRequest(*bifrostCtx, bifrostReq)⛔ Skipped due to learnings
Learnt from: Pratham-Mishra04 PR: maximhq/bifrost#63 File: transports/bifrost-http/integrations/openai/router.go:62-64 Timestamp: 2025-06-09T11:27:00.907Z Learning: The `lib.ConvertToBifrostContext` function in the bifrost HTTP transport never returns nil and handles the conversion internally, so nil checks are not needed when calling this function.
Learnt from: Pratham-Mishra04 PR: maximhq/bifrost#63 File: transports/bifrost-http/integrations/openai/router.go:62-64 Timestamp: 2025-06-09T11:27:00.907Z Learning: The `lib.ConvertToBifrostContext` function in the bifrost HTTP transport never returns nil and always returns a pointer to a valid context. It starts with context.Background() and only adds values to it, so nil checks are not needed when calling this function.
9bc0828
to
e339c57
Compare
2cbc913
to
2b7b78a
Compare
There was a problem hiding this 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 (9)
transports/bifrost-http/integrations/anthropic/router.go (4)
29-38
: Missing streaming-flag validation still unresolved.
The handler silently ignoresreq.Stream
, leading clients to believe they are getting a streaming response while the request is executed in non-streaming mode. Return501 Not Implemented
(or wire through once supported).
30-37
: JSON marshal error ignored – identical issue persists.
json.Marshal(errResponse)
errors are discarded (_
). This was flagged previously and is still unfixed. Propagate or at least log the marshal failure.
40-42
: Inconsistent error payload format.Unlike other error paths, this branch returns a plain string and no
Content-Type
. Standardise on JSON.
49-55
: Marshaling provider error loses detail & may fail.Serialising
err
directly may recurse on internal pointers and omit fields. Use a structured error or theError
field already present inschemas.BifrostError
. Also capture marshal errors.transports/bifrost-http/integrations/anthropic/types.go (5)
105-113
:Stream
flag still not propagated to Bifrost.Streaming intent is dropped; downstream layers never see it.
151-160
:tool_result
conversion still drops non-string payloads and ID mapping.Only plain text is copied; structured outputs/images are lost and
content
is ignored. Preserve the full JSON.
261-277
:ToolChoice
handling gated behindTools
presence – logic bug remains.Valid
tool_choice
withouttools
array is ignored.
265-269
: Enum casing not normalised.Upper-case values pass straight through; Anthropic expects lower-case.
284-291
:jsonifyInput
swallows marshal errors.Returning
"{}"
hides schema issues; log or propagate the error.
📜 Review details
Configuration used: CodeRabbit UI
Review profile: ASSERTIVE
Plan: Pro
📒 Files selected for processing (4)
core/providers/anthropic.go
(1 hunks)transports/bifrost-http/integrations/anthropic/router.go
(1 hunks)transports/bifrost-http/integrations/anthropic/types.go
(1 hunks)transports/bifrost-http/main.go
(2 hunks)
🧰 Additional context used
🧠 Learnings (1)
transports/bifrost-http/integrations/anthropic/types.go (1)
Learnt from: Pratham-Mishra04
PR: maximhq/bifrost#55
File: core/providers/anthropic.go:483-494
Timestamp: 2025-06-04T09:36:27.956Z
Learning: In the Anthropic provider (core/providers/anthropic.go), the user has confirmed through practical experience that the tool_choice parameter should always use an object format with a "type" field (e.g., {"type": "auto"}, {"type": "tool", "name": "function_name"}), even though the official documentation examples sometimes show "auto" as a direct string. The current implementation correctly handles all tool choice types with the object format.
🧬 Code Graph Analysis (1)
transports/bifrost-http/main.go (1)
transports/bifrost-http/integrations/anthropic/router.go (1)
NewAnthropicRouter
(18-20)
🔇 Additional comments (4)
transports/bifrost-http/main.go (2)
32-35
: Import order OK – no action needed.The additional Anthropic import is correct and does not introduce cyclic dependencies.
181-185
: Router slice update looks good.
anthropic.NewAnthropicRouter(client)
is appended toextensions
; no side-effects or ordering constraints.core/providers/anthropic.go (1)
483-490
:fallthrough
correctly unifies “function” / “tool” cases.The added
fallthrough
makes both enum strings map to the same payload, fixing prior incompatibility.transports/bifrost-http/integrations/anthropic/router.go (1)
47-52
:⚠️ Potential issueNil-pointer risk when
ConvertToBifrostContext
fails.
bifrostCtx
may benil
; dereferencing with*bifrostCtx
panics.bifrostCtx := lib.ConvertToBifrostContext(ctx) +if bifrostCtx == nil { + ctx.SetStatusCode(fasthttp.StatusInternalServerError) + ctx.SetContentType("application/json") + ctx.SetBodyString(`{"error":"internal context conversion failed"}`) + return +} -result, err := a.client.ChatCompletionRequest(*bifrostCtx, bifrostReq) +result, err := a.client.ChatCompletionRequest(*bifrostCtx, bifrostReq)⛔ Skipped due to learnings
Learnt from: Pratham-Mishra04 PR: maximhq/bifrost#63 File: transports/bifrost-http/integrations/openai/router.go:62-64 Timestamp: 2025-06-09T11:27:00.907Z Learning: The `lib.ConvertToBifrostContext` function in the bifrost HTTP transport never returns nil and handles the conversion internally, so nil checks are not needed when calling this function.
Learnt from: Pratham-Mishra04 PR: maximhq/bifrost#63 File: transports/bifrost-http/integrations/openai/router.go:62-64 Timestamp: 2025-06-09T11:27:00.907Z Learning: The `lib.ConvertToBifrostContext` function in the bifrost HTTP transport never returns nil and always returns a pointer to a valid context. It starts with context.Background() and only adds values to it, so nil checks are not needed when calling this function.
2b7b78a
to
c30de52
Compare
e339c57
to
1618f5d
Compare
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Actionable comments posted: 4
♻️ Duplicate comments (1)
transports/bifrost-http/integrations/anthropic/types.go (1)
261-278
:⚠️ Potential issue
tool_choice
ignored unlesstools
supplied
Placing the conversion insideif r.Tools != nil
means a valid request like
{"tool_choice":{"type":"auto"}}
is silently discarded when the caller provides notools
array.- if r.Tools != nil { - ... - bifrostReq.Params.Tools = &tools - - // Convert tool choice - if r.ToolChoice != nil { - ... - } - } + if r.Tools != nil { + ... + bifrostReq.Params.Tools = &tools + } + + // Convert tool choice (independent of tools) + if r.ToolChoice != nil { + toolChoice := &schemas.ToolChoice{ + Type: func() schemas.ToolChoiceType { + if r.ToolChoice.Type == "tool" { + return schemas.ToolChoiceTypeFunction + } + return schemas.ToolChoiceType(strings.ToLower(r.ToolChoice.Type)) + }(), + } + if r.ToolChoice.Type == "tool" && r.ToolChoice.Name != "" { + toolChoice.Function = schemas.ToolChoiceFunction{Name: r.ToolChoice.Name} + } + if bifrostReq.Params == nil { + bifrostReq.Params = &schemas.ModelParameters{} + } + bifrostReq.Params.ToolChoice = toolChoice + }
📜 Review details
Configuration used: CodeRabbit UI
Review profile: ASSERTIVE
Plan: Pro
📒 Files selected for processing (7)
core/providers/anthropic.go
(1 hunks)transports/bifrost-http/integrations/anthropic/router.go
(1 hunks)transports/bifrost-http/integrations/anthropic/types.go
(1 hunks)transports/bifrost-http/integrations/genai/router.go
(1 hunks)transports/bifrost-http/integrations/openai/router.go
(1 hunks)transports/bifrost-http/integrations/utils.go
(2 hunks)transports/bifrost-http/main.go
(2 hunks)
🧰 Additional context used
🧠 Learnings (2)
core/providers/anthropic.go (1)
Learnt from: Pratham-Mishra04
PR: maximhq/bifrost#55
File: core/providers/anthropic.go:483-494
Timestamp: 2025-06-04T09:36:27.956Z
Learning: In the Anthropic provider (core/providers/anthropic.go), the user has confirmed through practical experience that the tool_choice parameter should always use an object format with a "type" field (e.g., {"type": "auto"}, {"type": "tool", "name": "function_name"}), even though the official documentation examples sometimes show "auto" as a direct string. The current implementation correctly handles all tool choice types with the object format.
transports/bifrost-http/integrations/anthropic/types.go (1)
Learnt from: Pratham-Mishra04
PR: maximhq/bifrost#55
File: core/providers/anthropic.go:483-494
Timestamp: 2025-06-04T09:36:27.956Z
Learning: In the Anthropic provider (core/providers/anthropic.go), the user has confirmed through practical experience that the tool_choice parameter should always use an object format with a "type" field (e.g., {"type": "auto"}, {"type": "tool", "name": "function_name"}), even though the official documentation examples sometimes show "auto" as a direct string. The current implementation correctly handles all tool choice types with the object format.
🧬 Code Graph Analysis (4)
transports/bifrost-http/main.go (1)
transports/bifrost-http/integrations/anthropic/router.go (1)
NewAnthropicRouter
(16-39)
transports/bifrost-http/integrations/openai/router.go (1)
transports/bifrost-http/integrations/openai/types.go (1)
OpenAIChatRequest
(36-57)
transports/bifrost-http/integrations/genai/router.go (1)
transports/bifrost-http/integrations/genai/types.go (1)
GeminiChatRequest
(28-39)
transports/bifrost-http/integrations/anthropic/types.go (3)
core/utils.go (1)
Ptr
(3-5)core/schemas/bifrost.go (21)
ToolChoiceTypeFunction
(126-126)ToolChoice
(137-140)BifrostRequest
(54-64)Anthropic
(36-36)RequestInput
(46-49)BifrostMessage
(143-152)ModelChatMessageRoleSystem
(25-25)ModelChatMessageRole
(20-20)ToolCall
(266-270)Function
(101-105)FunctionCall
(260-263)AssistantMessage
(166-171)ModelChatMessageRoleTool
(27-27)ToolMessage
(160-163)ModelParameters
(75-89)Tool
(108-112)FunctionParameters
(92-98)ToolChoiceType
(116-116)ToolChoiceFunction
(132-134)BifrostResponse
(184-194)LLMUsage
(197-203)core/providers/anthropic.go (1)
AnthropicToolChoice
(20-24)
🔇 Additional comments (7)
transports/bifrost-http/main.go (2)
32-32
: Proper import structure for Anthropic integration.The import follows the established pattern and naming convention used by other integrations.
184-184
: Correct registration of Anthropic router.The Anthropic router is properly registered in the extensions slice, following the same pattern as GenAI and OpenAI routers. This ensures the
/anthropic/v1/messages
endpoint will be available.core/providers/anthropic.go (1)
485-487
: Improved tool choice handling with unified logic.The
fallthrough
statement effectively consolidates the handling ofschemas.ToolChoiceTypeFunction
and"tool"
cases, ensuring both execute the same logic that setstool_choice
with type"tool"
and the function name. This reduces code duplication and aligns with the established pattern of using object format for tool choices.transports/bifrost-http/integrations/utils.go (2)
42-42
: Enhanced concurrency safety with factory function pattern.Replacing the static
RequestType
field withGetRequestTypeInstance
function ensures each HTTP request gets a fresh request instance, preventing potential data races and memory issues in concurrent scenarios.
97-97
: Correct implementation of factory function usage.The call to
config.GetRequestTypeInstance()
properly creates a new request instance for each handler invocation, supporting the thread-safe request processing architecture.transports/bifrost-http/integrations/genai/router.go (1)
24-26
: Proper adoption of factory function pattern.The GenAI router correctly implements the new
GetRequestTypeInstance
pattern, ensuring freshGeminiChatRequest
instances for each request. This change aligns with the broader refactoring to improve concurrency safety across all integration routers.transports/bifrost-http/integrations/openai/router.go (1)
21-23
: Factory func is the right call – good alignment with utils refactor
Replacing the staticRequestType
withGetRequestTypeInstance
prevents cross-request data leakage. Looks clean.
1618f5d
to
bb0425c
Compare
15286f9
to
5e6692a
Compare
bb0425c
to
c664c44
Compare
5e6692a
to
2841d24
Compare
efe4ba6
to
46def42
Compare
2841d24
to
a008712
Compare
There was a problem hiding this 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
🔭 Outside diff range comments (1)
transports/bifrost-http/integrations/utils.go (1)
98-110
:⚠️ Potential issueReturned request instance can be nil
json.Unmarshal
with anil
destination triggerspanic: runtime error: invalid memory address
.
Even with the above struct check, a buggy factory function could still returnnil
. Add a guard before unmarshalling.- if method != "GET" && method != "DELETE" { + if req == nil { + g.sendError(ctx, fasthttp.StatusInternalServerError, "request factory returned nil") + return + } + + if method != "GET" && method != "DELETE" {
♻️ Duplicate comments (6)
transports/bifrost-http/integrations/anthropic/router.go (1)
21-33
: 💡 Verification agent🧩 Analysis chain
ResponseFunc
may return nil → sends200 null
DeriveAnthropicFromBifrostResponse
can legitimately returnnil
(e.g., internal error).
GenericRouter.sendSuccess
will happily marshal that as the literal JSON wordnull
with status 200.Consider hard-failing or mapping to a structured error instead:
- ResponseFunc: func(resp *schemas.BifrostResponse) interface{} { - return DeriveAnthropicFromBifrostResponse(resp) - }, + ResponseFunc: func(resp *schemas.BifrostResponse) interface{} { + out := DeriveAnthropicFromBifrostResponse(resp) + if out == nil { + return map[string]string{"error": "empty response from core"} + } + return out + },
🏁 Script executed:
#!/bin/bash set -e # Locate the Anthropich router file file=$(rg -l "AnthropicMessageRequest") echo "Found file: $file" # Find the DeriveAnthropicFromBifrostResponse references and definition echo -e "\n=== References to DeriveAnthropicFromBifrostResponse ===" rg -n "DeriveAnthropicFromBifrostResponse" "$file" echo -e "\n=== Implementation of DeriveAnthropicFromBifrostResponse ===" rg -n "func DeriveAnthropicFromBifrostResponse" -C5 "$file" # Inspect GenericRouter.sendSuccess to see how nil is handled echo -e "\n=== sendSuccess implementation (context) ===" rg -n "sendSuccess" -C5 .Length of output: 862
🏁 Script executed:
#!/bin/bash set -e echo "=== DeriveAnthropicFromBifrostResponse references in anthropic directory ===" rg -n "DeriveAnthropicFromBifrostResponse" -C3 transports/bifrost-http/integrations/anthropic echo -e "\n=== Definition of DeriveAnthropicFromBifrostResponse ===" rg -n "func .*DeriveAnthropicFromBifrostResponse" -C5 . echo -e "\n=== sendSuccess implementation in GenericRouter ===" rg -n "sendSuccess" -C5 .Length of output: 4884
🏁 Script executed:
#!/bin/bash set -e echo "=== Integration wrapper error handling & response flow ===" sed -n '130,200p' transports/bifrost-http/integrations/utils.goLength of output: 1972
Prevent
200 null
by guarding against nil in ResponseFuncThe current
ResponseFunc
returnsnil
whenDeriveAnthropicFromBifrostResponse
yieldsnil
(e.g. if the core response is nil), andsendSuccess
then serializes that as a literal JSONnull
with HTTP 200. To avoid returning an empty payload, explicitly map nil outputs to a structured error.• File:
transports/bifrost-http/integrations/anthropic/router.go
• Update theResponseFunc
block as follows:- ResponseFunc: func(resp *schemas.BifrostResponse) interface{} { - return DeriveAnthropicFromBifrostResponse(resp) - }, + ResponseFunc: func(resp *schemas.BifrostResponse) interface{} { + out := DeriveAnthropicFromBifrostResponse(resp) + if out == nil { + // surface an error instead of 200 null + return map[string]string{"error": "empty response from core"} + } + return out + },This ensures callers receive a JSON error object instead of an unhelpful
null
.transports/bifrost-http/integrations/anthropic/types.go (5)
11-12
: 🧹 Nitpick (assertive)Inline the function-type pointer – global var adds needless indirection
This was raised earlier and is still unresolved.
fnTypePtr
is used once; inlinebifrost.Ptr(string(schemas.ToolChoiceTypeFunction))
where needed and drop the global.
125-161
:⚠️ Potential issueImage, structured
tool_result
, and multimodal content are silently discardedThe switch only handles
"text"
,"tool_use"
, and a very lossy"tool_result"
mapping.
All"image"
blocks and non-stringtool_result.content
are ignored, leading to data loss for multimodal requests and structured tool output.Recommend:
- Add a case for
"image"
that maps to an appropriateschemas.ImageContent
or preserves raw payload.- Preserve entire
tool_result.content
(marshal to JSON string, store inToolMessage.Content
, etc.) instead of extracting only strings.
206-278
: 🛠️ Refactor suggestion
tool_choice
conversion still gated byr.Tools != nil
When a caller sends
tool_choice
but omits atools
array (valid Anthropic usage), the choice is silently dropped because this block is nested insideif r.Tools != nil
. Move the choice mapping outside the guard.Also,
Type
is forwarded without case normalisation –"Auto"
becomes invalid upstream.- if r.Tools != nil { ... - // Convert tool choice - if r.ToolChoice != nil { + if r.Tools != nil { ... + } + + // Convert tool choice (independent of tools presence) + if r.ToolChoice != nil { toolChoice := &schemas.ToolChoice{ - Type: func() schemas.ToolChoiceType { - if r.ToolChoice.Type == "tool" { - return schemas.ToolChoiceTypeFunction - } - return schemas.ToolChoiceType(r.ToolChoice.Type) - }(), + Type: func() schemas.ToolChoiceType { + t := strings.ToLower(r.ToolChoice.Type) + if t == "tool" { + return schemas.ToolChoiceTypeFunction + } + return schemas.ToolChoiceType(t) + }(), }
284-292
: 🧹 Nitpick (assertive)
jsonifyInput
swallows marshal errors – hides bad schemasReturning
"{}"
masks real problems and complicates debugging.Either propagate the error back (preferred) or at least log it:
- jsonBytes, err := json.Marshal(input) - if err != nil { - return "{}" - } - return string(jsonBytes) + jsonBytes, err := json.Marshal(input) + if err != nil { + log.Printf("[anthropic] failed to marshal tool input: %v", err) + return "{}" + } + return string(jsonBytes)
335-372
:⚠️ Potential issue
DeriveAnthropicFromBifrostResponse
dropsthinking
andtool_result
blocks & may emitcontent:null
- Assistant thoughts (
AssistantMessage.Thought
) andtool_result
messages are not propagated, breaking round-trip fidelity.- If no content is generated,
anthropicResp.Content
staysnil
→ JSON"content": null
, which violates Anthropic’s spec (must be an array).
📜 Review details
Configuration used: CodeRabbit UI
Review profile: ASSERTIVE
Plan: Pro
📒 Files selected for processing (7)
core/providers/anthropic.go
(1 hunks)transports/bifrost-http/integrations/anthropic/router.go
(1 hunks)transports/bifrost-http/integrations/anthropic/types.go
(1 hunks)transports/bifrost-http/integrations/genai/router.go
(1 hunks)transports/bifrost-http/integrations/openai/router.go
(1 hunks)transports/bifrost-http/integrations/utils.go
(2 hunks)transports/bifrost-http/main.go
(2 hunks)
🧰 Additional context used
🧠 Learnings (2)
core/providers/anthropic.go (1)
Learnt from: Pratham-Mishra04
PR: maximhq/bifrost#55
File: core/providers/anthropic.go:483-494
Timestamp: 2025-06-04T09:36:27.956Z
Learning: In the Anthropic provider (core/providers/anthropic.go), the user has confirmed through practical experience that the tool_choice parameter should always use an object format with a "type" field (e.g., {"type": "auto"}, {"type": "tool", "name": "function_name"}), even though the official documentation examples sometimes show "auto" as a direct string. The current implementation correctly handles all tool choice types with the object format.
transports/bifrost-http/integrations/anthropic/types.go (2)
Learnt from: Pratham-Mishra04
PR: maximhq/bifrost#55
File: core/providers/anthropic.go:483-494
Timestamp: 2025-06-04T09:36:27.956Z
Learning: In the Anthropic provider (core/providers/anthropic.go), the user has confirmed through practical experience that the tool_choice parameter should always use an object format with a "type" field (e.g., {"type": "auto"}, {"type": "tool", "name": "function_name"}), even though the official documentation examples sometimes show "auto" as a direct string. The current implementation correctly handles all tool choice types with the object format.
Learnt from: Pratham-Mishra04
PR: maximhq/bifrost#65
File: transports/bifrost-http/integrations/anthropic/types.go:105-113
Timestamp: 2025-06-09T14:56:14.936Z
Learning: Streaming functionality is not yet supported in the Bifrost system, so Stream flags are intentionally not propagated from integration requests to BifrostRequest.
🧬 Code Graph Analysis (3)
transports/bifrost-http/main.go (1)
transports/bifrost-http/integrations/anthropic/router.go (1)
NewAnthropicRouter
(16-39)
transports/bifrost-http/integrations/openai/router.go (1)
transports/bifrost-http/integrations/openai/types.go (1)
OpenAIChatRequest
(36-57)
transports/bifrost-http/integrations/genai/router.go (1)
transports/bifrost-http/integrations/genai/types.go (1)
GeminiChatRequest
(29-40)
🔇 Additional comments (4)
transports/bifrost-http/main.go (1)
46-46
: LGTM! Clean integration of Anthropic router.The import and router registration follow the established pattern used for GenAI and OpenAI integrations. The documentation already includes the Anthropic endpoint example, showing good consistency.
Also applies to: 198-198
core/providers/anthropic.go (1)
485-487
: LGTM! Improved tool choice handling for Anthropic integration.The fallthrough ensures that both
ToolChoiceTypeFunction
and"tool"
types are handled consistently, setting the tool choice with"type": "tool"
format. This aligns with Anthropic's API requirements and supports the new integration.transports/bifrost-http/integrations/openai/router.go (1)
21-23
: LGTM! Improved request instance handling.The factory function pattern ensures fresh
OpenAIChatRequest
instances per request, preventing potential issues with reusing instances across concurrent requests. This follows the consistent refactoring pattern applied across integration routers.transports/bifrost-http/integrations/genai/router.go (1)
24-26
: LGTM! Consistent request instance handling.The factory function pattern ensures fresh
GeminiChatRequest
instances per request, maintaining consistency with the refactoring applied across all integration routers for improved thread safety.
a008712
to
78ab5c4
Compare
46def42
to
65a8762
Compare
78ab5c4
to
14088f7
Compare
There was a problem hiding this 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 (7)
transports/bifrost-http/integrations/utils.go (2)
40-46
: Still missing nil-guards on factory / converter – runtime panic remains possiblePrior feedback already highlighted that
GetRequestTypeInstance
andRequestConverter
must be checked fornil
before use.
Neither the struct tag norcreateHandler
adds such guards, so an accidentally un-initialised route will crash the server on first request.
Please add the defensive checks shown in the previous review.
98-98
: Dereferencing uncheckedGetRequestTypeInstance
repeats the panic risk
req := config.GetRequestTypeInstance()
is executed unconditionally.
If the factory isnil
the handler panics, taking down the entire HTTP process.
Add:+if config.GetRequestTypeInstance == nil { + g.sendError(ctx, fasthttp.StatusInternalServerError, "route mis-configuration") + return +}transports/bifrost-http/integrations/anthropic/types.go (5)
11-11
: Inline the constant – extra global adds noise
fnTypePtr
is just a pointer to the literal"function"
. Inlinebifrost.Ptr(string(schemas.ToolChoiceTypeFunction))
where used and drop the package-level var.
262-278
:tool_choice
conversion is skipped whentools
is nilThe mapping sits inside the
if r.Tools != nil
block, so valid requests that specifytool_choice
without atools
array drop the field.Move the
tool_choice
logic outside the tools branch as flagged earlier.
285-293
:jsonifyInput
swallows marshal errors – hides bad tool inputsReturning
"{}"
on error masks schema problems and makes debugging painful.
Log the error or propagate it so callers can react.
335-384
: Nilcontent
encodes asnull
, violating Anthropic specWhen no blocks are added,
content
staysnil
and JSON marshals tonull
.
Initialise an empty slice to ensure"content":[]
.var content []AnthropicContent ... - anthropicResp.Content = content + if content == nil { + content = []AnthropicContent{} + } + anthropicResp.Content = content
157-171
: 🛠️ Refactor suggestion
tool_result
content loses the actual result payloadOnly
ToolCallID
(and maybe an image) gets forwarded;content.Content
(the tool’s return data) is silently discarded.
Downstream consumers therefore cannot read the tool output.case "tool_result": if content.ToolUseID != nil { bifrostMsg.ToolMessage = &schemas.ToolMessage{ ToolCallID: content.ToolUseID, + // Preserve textual / structured result if present + Content: func() *string { + if content.Content == nil { + return nil + } + bytes, _ := json.Marshal(content.Content) + s := string(bytes) + return &s + }(), } ... }Adjust the field names to match
schemas.ToolMessage
.
📜 Review details
Configuration used: CodeRabbit UI
Review profile: ASSERTIVE
Plan: Pro
📒 Files selected for processing (7)
core/providers/anthropic.go
(1 hunks)transports/bifrost-http/integrations/anthropic/router.go
(1 hunks)transports/bifrost-http/integrations/anthropic/types.go
(1 hunks)transports/bifrost-http/integrations/genai/router.go
(1 hunks)transports/bifrost-http/integrations/openai/router.go
(1 hunks)transports/bifrost-http/integrations/utils.go
(2 hunks)transports/bifrost-http/main.go
(2 hunks)
🧰 Additional context used
🧠 Learnings (2)
transports/bifrost-http/integrations/anthropic/router.go (1)
Learnt from: Pratham-Mishra04
PR: maximhq/bifrost#65
File: transports/bifrost-http/integrations/anthropic/router.go:19-33
Timestamp: 2025-06-09T16:46:31.997Z
Learning: In the GenericRouter (transports/bifrost-http/integrations), ResponseFunc is not called if the BifrostResponse parameter is nil, providing built-in protection against nil response marshaling.
transports/bifrost-http/integrations/anthropic/types.go (4)
Learnt from: Pratham-Mishra04
PR: maximhq/bifrost#65
File: transports/bifrost-http/integrations/anthropic/types.go:261-278
Timestamp: 2025-06-09T17:12:55.169Z
Learning: Anthropic's API consistently returns tool_choice enum values in lowercase only ("auto", "none", "any", "tool"), so case normalization is not needed when processing these values in the Anthropic integration layer.
Learnt from: Pratham-Mishra04
PR: maximhq/bifrost#55
File: core/providers/anthropic.go:483-494
Timestamp: 2025-06-04T09:36:27.956Z
Learning: In the Anthropic provider (core/providers/anthropic.go), the user has confirmed through practical experience that the tool_choice parameter should always use an object format with a "type" field (e.g., {"type": "auto"}, {"type": "tool", "name": "function_name"}), even though the official documentation examples sometimes show "auto" as a direct string. The current implementation correctly handles all tool choice types with the object format.
Learnt from: Pratham-Mishra04
PR: maximhq/bifrost#65
File: transports/bifrost-http/integrations/anthropic/types.go:105-113
Timestamp: 2025-06-09T14:56:14.936Z
Learning: Streaming functionality is not yet supported in the Bifrost system, so Stream flags are intentionally not propagated from integration requests to BifrostRequest.
Learnt from: Pratham-Mishra04
PR: maximhq/bifrost#65
File: transports/bifrost-http/integrations/anthropic/types.go:326-376
Timestamp: 2025-06-09T16:56:44.370Z
Learning: In Anthropic's message format, `tool_result` content blocks are inputs sent TO the LLM (typically from user/system after tool execution), not outputs generated BY the LLM. LLM responses should only contain `text` and `tool_use` content types.
🧬 Code Graph Analysis (4)
transports/bifrost-http/main.go (1)
transports/bifrost-http/integrations/anthropic/router.go (1)
NewAnthropicRouter
(16-39)
transports/bifrost-http/integrations/genai/router.go (1)
transports/bifrost-http/integrations/genai/types.go (1)
GeminiChatRequest
(28-39)
transports/bifrost-http/integrations/anthropic/router.go (2)
transports/bifrost-http/integrations/utils.go (4)
GenericRouter
(52-55)RouteConfig
(39-47)RequestConverter
(21-21)NewGenericRouter
(59-64)transports/bifrost-http/integrations/anthropic/types.go (2)
AnthropicMessageRequest
(90-102)DeriveAnthropicFromBifrostResponse
(315-386)
transports/bifrost-http/integrations/anthropic/types.go (3)
core/utils.go (1)
Ptr
(3-5)core/schemas/bifrost.go (21)
ToolChoiceTypeFunction
(126-126)ToolChoice
(137-140)BifrostRequest
(54-64)Anthropic
(36-36)RequestInput
(46-49)BifrostMessage
(143-152)ModelChatMessageRole
(20-20)ToolCall
(266-270)UserMessage
(155-157)ImageContent
(174-179)Function
(101-105)FunctionCall
(260-263)ToolMessage
(160-163)AssistantMessage
(166-171)ModelParameters
(75-89)Tool
(108-112)FunctionParameters
(92-98)ToolChoiceType
(116-116)ToolChoiceFunction
(132-134)BifrostResponse
(184-194)LLMUsage
(197-203)core/providers/anthropic.go (1)
AnthropicToolChoice
(20-24)
🔇 Additional comments (4)
transports/bifrost-http/main.go (1)
48-48
: LGTM! Clean integration of Anthropic support.The import and router registration follow the established pattern for AI provider integrations. The implementation is consistent with the existing GenAI and OpenAI integrations.
Also applies to: 200-200
core/providers/anthropic.go (1)
486-487
: LGTM! Unifies tool choice handling.The fallthrough statement correctly unifies handling of both "function" and "tool" types, ensuring compatibility between different tool choice representations while maintaining the same parameter structure for Anthropic's API.
transports/bifrost-http/integrations/openai/router.go (1)
21-23
: LGTM! Improved thread safety with factory pattern.The factory function ensures each HTTP request gets a fresh
OpenAIChatRequest
instance, preventing potential shared state issues between concurrent requests.transports/bifrost-http/integrations/genai/router.go (1)
24-26
: LGTM! Consistent factory pattern implementation.The factory function correctly mirrors the same pattern applied to the OpenAI router, ensuring fresh
GeminiChatRequest
instances per HTTP request and maintaining consistency across all integration routers.
14088f7
to
317ed8a
Compare
e009a8b
to
0709d38
Compare
c9f43b6
to
4c58221
Compare
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Actionable comments posted: 2
♻️ Duplicate comments (2)
transports/bifrost-http/integrations/anthropic/types.go (2)
11-12
: Redundant globalfnTypePtr
variableThe helper is only used in one place and can be inlined with
bifrost.Ptr(...)
. Removing the package-level var reduces indirection.
310-318
:jsonifyInput
hides marshal errors, hampering debuggingReturning
"{}"
silently whenjson.Marshal
fails makes diagnosing schema issues difficult.
Log the error (or propagate it) before falling back.This concern has been raised previously but is still unresolved.
📜 Review details
Configuration used: CodeRabbit UI
Review profile: ASSERTIVE
Plan: Pro
📒 Files selected for processing (7)
core/providers/anthropic.go
(1 hunks)transports/bifrost-http/integrations/anthropic/router.go
(1 hunks)transports/bifrost-http/integrations/anthropic/types.go
(1 hunks)transports/bifrost-http/integrations/genai/router.go
(1 hunks)transports/bifrost-http/integrations/openai/router.go
(1 hunks)transports/bifrost-http/integrations/utils.go
(5 hunks)transports/bifrost-http/main.go
(2 hunks)
🧰 Additional context used
🧠 Learnings (4)
core/providers/anthropic.go (1)
Learnt from: Pratham-Mishra04
PR: maximhq/bifrost#55
File: core/providers/anthropic.go:483-494
Timestamp: 2025-06-04T09:36:27.956Z
Learning: In the Anthropic provider (core/providers/anthropic.go), the user has confirmed through practical experience that the tool_choice parameter should always use an object format with a "type" field (e.g., {"type": "auto"}, {"type": "tool", "name": "function_name"}), even though the official documentation examples sometimes show "auto" as a direct string. The current implementation correctly handles all tool choice types with the object format.
transports/bifrost-http/integrations/anthropic/router.go (3)
Learnt from: Pratham-Mishra04
PR: maximhq/bifrost#65
File: transports/bifrost-http/integrations/anthropic/router.go:19-33
Timestamp: 2025-06-09T16:46:32.018Z
Learning: In the GenericRouter (transports/bifrost-http/integrations), ResponseFunc is not called if the BifrostResponse parameter is nil, providing built-in protection against nil response marshaling.
Learnt from: Pratham-Mishra04
PR: maximhq/bifrost#67
File: transports/bifrost-http/integrations/anthropic/router.go:26-34
Timestamp: 2025-06-10T11:19:29.578Z
Learning: The Generic router in transports/bifrost-http/integrations/utils.go already handles nil pointers from RequestConverter functions. When a RequestConverter returns a nil *schemas.BifrostRequest, the Generic router automatically returns an HTTP 400 error, making additional nil checks in individual router implementations redundant.
Learnt from: Pratham-Mishra04
PR: maximhq/bifrost#67
File: transports/bifrost-http/integrations/anthropic/router.go:26-34
Timestamp: 2025-06-10T11:19:29.578Z
Learning: The Generic router in transports/bifrost-http/integrations/utils.go already handles nil pointers from RequestConverter functions. When a RequestConverter returns a nil *schemas.BifrostRequest, the Generic router automatically returns an HTTP 400 error with "Invalid request" message, making additional nil checks in individual router implementations redundant.
transports/bifrost-http/integrations/utils.go (3)
Learnt from: Pratham-Mishra04
PR: maximhq/bifrost#67
File: transports/bifrost-http/integrations/anthropic/router.go:26-34
Timestamp: 2025-06-10T11:19:29.578Z
Learning: The Generic router in transports/bifrost-http/integrations/utils.go already handles nil pointers from RequestConverter functions. When a RequestConverter returns a nil *schemas.BifrostRequest, the Generic router automatically returns an HTTP 400 error, making additional nil checks in individual router implementations redundant.
Learnt from: Pratham-Mishra04
PR: maximhq/bifrost#67
File: transports/bifrost-http/integrations/anthropic/router.go:26-34
Timestamp: 2025-06-10T11:19:29.578Z
Learning: The Generic router in transports/bifrost-http/integrations/utils.go already handles nil pointers from RequestConverter functions. When a RequestConverter returns a nil *schemas.BifrostRequest, the Generic router automatically returns an HTTP 400 error with "Invalid request" message, making additional nil checks in individual router implementations redundant.
Learnt from: Pratham-Mishra04
PR: maximhq/bifrost#65
File: transports/bifrost-http/integrations/utils.go:169-173
Timestamp: 2025-06-09T17:33:52.234Z
Learning: The ChatCompletionRequest method in the Bifrost client follows a contract where the result parameter will never be nil if the error parameter is nil. This means when error checking passes (err == nil), the result is guaranteed to be valid and can be safely used without additional nil checks.
transports/bifrost-http/integrations/anthropic/types.go (9)
Learnt from: Pratham-Mishra04
PR: maximhq/bifrost#65
File: transports/bifrost-http/integrations/anthropic/types.go:131-180
Timestamp: 2025-06-10T13:11:37.842Z
Learning: In Anthropic API integration for Bifrost, messages won't contain both image and tool_result content blocks in the same message, so defensive guards against multiple embedded message structs are unnecessary in the content processing loop.
Learnt from: Pratham-Mishra04
PR: maximhq/bifrost#65
File: transports/bifrost-http/integrations/anthropic/types.go:261-278
Timestamp: 2025-06-09T17:12:55.222Z
Learning: Anthropic's API consistently returns tool_choice enum values in lowercase only ("auto", "none", "any", "tool"), so case normalization is not needed when processing these values in the Anthropic integration layer.
Learnt from: Pratham-Mishra04
PR: maximhq/bifrost#55
File: core/providers/anthropic.go:483-494
Timestamp: 2025-06-04T09:36:27.956Z
Learning: In the Anthropic provider (core/providers/anthropic.go), the user has confirmed through practical experience that the tool_choice parameter should always use an object format with a "type" field (e.g., {"type": "auto"}, {"type": "tool", "name": "function_name"}), even though the official documentation examples sometimes show "auto" as a direct string. The current implementation correctly handles all tool choice types with the object format.
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.
Learnt from: Pratham-Mishra04
PR: maximhq/bifrost#65
File: transports/bifrost-http/integrations/anthropic/types.go:105-113
Timestamp: 2025-06-09T14:56:14.951Z
Learning: Streaming functionality is not yet supported in the Bifrost system, so Stream flags are intentionally not propagated from integration requests to BifrostRequest.
Learnt from: Pratham-Mishra04
PR: maximhq/bifrost#65
File: transports/bifrost-http/integrations/anthropic/types.go:326-376
Timestamp: 2025-06-09T16:56:44.395Z
Learning: In Anthropic's message format, `tool_result` content blocks are inputs sent TO the LLM (typically from user/system after tool execution), not outputs generated BY the LLM. LLM responses should only contain `text` and `tool_use` content types.
Learnt from: Pratham-Mishra04
PR: maximhq/bifrost#64
File: transports/bifrost-http/integrations/genai/types.go:383-395
Timestamp: 2025-06-09T16:26:05.777Z
Learning: In the Bifrost schema (core/schemas/bifrost.go), only UserMessage and ToolMessage structs have ImageContent fields. AssistantMessage does not have an ImageContent field and cannot contain images. The schema design intentionally limits image content to user and tool messages only.
Learnt from: Pratham-Mishra04
PR: maximhq/bifrost#65
File: transports/bifrost-http/integrations/anthropic/types.go:129-145
Timestamp: 2025-06-10T11:12:26.840Z
Learning: Anthropic API does not support tool roles and images can only be present in user messages, not assistant or tool messages. Therefore, in Anthropic integration code, image content should always be assigned to UserMessage regardless of any other considerations.
Learnt from: Pratham-Mishra04
PR: maximhq/bifrost#65
File: transports/bifrost-http/integrations/anthropic/types.go:131-180
Timestamp: 2025-06-10T13:03:26.975Z
Learning: In Anthropic API message format, tool_result content blocks are sent by users in response to assistant tool calls, while image content blocks are typically sent in initial user messages. These content types follow different conversation flows and wouldn't naturally appear together in a single message, making defensive guards against multiple embedded message types unnecessary.
🧬 Code Graph Analysis (3)
transports/bifrost-http/main.go (1)
transports/bifrost-http/integrations/anthropic/router.go (1)
NewAnthropicRouter
(16-39)
transports/bifrost-http/integrations/genai/router.go (1)
transports/bifrost-http/integrations/genai/types.go (1)
GeminiChatRequest
(28-39)
transports/bifrost-http/integrations/anthropic/types.go (3)
core/utils.go (1)
Ptr
(3-5)core/schemas/bifrost.go (23)
ToolChoiceTypeFunction
(126-126)ToolChoice
(137-140)BifrostRequest
(54-64)Anthropic
(36-36)RequestInput
(46-49)BifrostMessage
(143-152)ModelChatMessageRoleSystem
(25-25)ModelChatMessageRole
(20-20)ToolCall
(273-277)UserMessage
(155-157)ImageContent
(181-186)Function
(101-105)FunctionCall
(267-270)ToolMessage
(160-163)ModelChatMessageRoleTool
(27-27)AssistantMessage
(166-171)ModelParameters
(75-89)Tool
(108-112)FunctionParameters
(92-98)ToolChoiceType
(116-116)ToolChoiceFunction
(132-134)BifrostResponse
(191-201)LLMUsage
(204-210)core/providers/anthropic.go (1)
AnthropicToolChoice
(20-24)
⏰ Context from checks skipped due to timeout of 90000ms (2)
- GitHub Check: Graphite / mergeability_check
- GitHub Check: Graphite / mergeability_check
🔇 Additional comments (7)
transports/bifrost-http/main.go (1)
48-48
: LGTM! Clean integration following established patterns.The Anthropic integration is properly imported and registered alongside existing providers, maintaining consistency with the established architecture.
Also applies to: 200-200
core/providers/anthropic.go (1)
492-493
: LGTM! Proper unification of equivalent tool choice types.The fallthrough correctly consolidates handling of
schemas.ToolChoiceTypeFunction
and"tool"
since both should use the same object format in Anthropic's API.transports/bifrost-http/integrations/openai/router.go (1)
21-23
: LGTM! Improved thread safety with dynamic request instantiation.Replacing the static
RequestType
withGetRequestTypeInstance
ensures each request gets a fresh instance, preventing potential data leakage between concurrent requests.transports/bifrost-http/integrations/genai/router.go (1)
24-26
: LGTM! Consistent dynamic instantiation pattern.The change maintains consistency with other integration routers and provides the same thread safety benefits through dynamic request instantiation.
transports/bifrost-http/integrations/utils.go (3)
72-89
: Excellent startup validation implementation!The comprehensive validation at route registration time addresses previous performance concerns by failing fast during startup rather than checking on every request. The validation covers all critical fields and even tests the factory function.
119-119
: LGTM! Dynamic request instantiation improves thread safety.Using
GetRequestTypeInstance()
ensures each request gets a fresh instance, preventing potential data corruption in concurrent scenarios.
176-179
: Good defensive programming with the post-callback nil check.While the Bifrost client contract guarantees non-nil results when there's no error, this additional check provides protection against potential issues introduced by post-request callbacks.
Merge activity
|
4c58221
to
684f6ee
Compare
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Bug: Image Overwrite and Type Mismatch Bug
In ConvertToBifrostRequest
, when an Anthropic message contains multiple image content blocks, only the last image is preserved for both UserMessage
and ToolMessage
image content, as previous images are overwritten. Additionally, the Type
field within schemas.ImageContent
is incorrectly assigned a *string
from content.Source.Type
instead of the expected *schemas.ImageContentType
enum value.
transports/bifrost-http/integrations/anthropic/types.go#L137-L147
bifrost/transports/bifrost-http/integrations/anthropic/types.go
Lines 137 to 147 in 684f6ee
} | |
case "image": | |
if content.Source != nil { | |
bifrostMsg.UserMessage = &schemas.UserMessage{ | |
ImageContent: &schemas.ImageContent{ | |
Type: bifrost.Ptr(content.Source.Type), | |
URL: content.Source.Data, | |
MediaType: &content.Source.MediaType, | |
}, | |
} | |
} |
Was this report helpful? Give feedback by reacting with 👍 or 👎
Add Anthropic API Compatibility Layer
This PR adds a native Anthropic API compatibility layer to Bifrost, allowing applications built for Anthropic's API to work with Bifrost without modification.
Key changes:
/anthropic/v1/messages
endpoint that mirrors Anthropic's Messages APIThis implementation handles all Anthropic-specific features including: