Skip to content

Commit a128370

Browse files
akshaydeoslyang08
authored andcommitted
fix: set fixed index 0 for stream responses and remove nil check for usage (#983)
Fixed inconsistencies in stream response handling for Anthropic and Bedrock providers by standardizing index values and removing unnecessary conditional checks. - Removed conditional check for `usage` in Anthropic response handling, ensuring usage is always assigned - Changed dynamic index values to fixed `0` index in stream responses for both Anthropic and Bedrock providers - Removed unnecessary content block index handling in Bedrock provider - [x] Bug fix - [ ] Feature - [x] Refactor - [ ] Documentation - [ ] Chore/CI - [x] Core (Go) - [ ] Transports (HTTP) - [x] Providers/Integrations - [ ] Plugins - [ ] UI (Next.js) - [ ] Docs Test streaming responses from Anthropic and Bedrock providers to ensure proper index values and usage information: ```sh go version go test ./core/providers/anthropic/... go test ./core/providers/bedrock/... ``` - [ ] Yes - [x] No Fixes inconsistencies in stream response handling across providers. No security implications. - [x] I read `docs/contributing/README.md` and followed the guidelines - [x] I added/updated tests where appropriate - [ ] I updated documentation where needed - [x] I verified builds succeed (Go and UI) - [x] I verified the CI pipeline passes locally if applicable
2 parents 3f2a3fa + 07655d7 commit a128370

File tree

11 files changed

+56
-25
lines changed

11 files changed

+56
-25
lines changed

core/bifrost.go

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2504,12 +2504,22 @@ func (bifrost *Bifrost) selectKeyFromProviderForModel(ctx *context.Context, requ
25042504
if requestType == schemas.ListModelsRequest {
25052505
// Skip deployment check but still check if the key has a value
25062506
for _, k := range keys {
2507+
// Skip disabled keys
2508+
if k.Enabled != nil && !*k.Enabled {
2509+
continue
2510+
}
2511+
25072512
if strings.TrimSpace(k.Value) != "" || canProviderKeyValueBeEmpty(baseProviderType) {
25082513
supportedKeys = append(supportedKeys, k)
25092514
}
25102515
}
25112516
} else {
25122517
for _, key := range keys {
2518+
// Skip disabled keys
2519+
if key.Enabled != nil && !*key.Enabled {
2520+
continue
2521+
}
2522+
25132523
modelSupported := (slices.Contains(key.Models, model) && (strings.TrimSpace(key.Value) != "" || canProviderKeyValueBeEmpty(baseProviderType))) || len(key.Models) == 0
25142524

25152525
// Additional deployment checks for Azure, Bedrock and Vertex

core/changelog.md

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1 +1,2 @@
1-
fix: vertex and bedrock usage aggregation improvements for streaming
1+
fix: vertex and bedrock usage aggregation improvements for streaming
2+
fix: choice index fixed to 0 for anthropic and bedrock streaming

core/providers/anthropic/anthropic.go

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -931,9 +931,7 @@ func HandleAnthropicResponsesStream(
931931
if response.Response == nil {
932932
response.Response = &schemas.BifrostResponsesResponse{}
933933
}
934-
if usage != nil {
935-
response.Response.Usage = usage
936-
}
934+
response.Response.Usage = usage
937935
response.ExtraFields.Latency = time.Since(startTime).Milliseconds()
938936
ctx = context.WithValue(ctx, schemas.BifrostContextKeyStreamEndIndicator, true)
939937
providerUtils.ProcessAndSendResponse(ctx, postHookRunner, providerUtils.GetBifrostResponseForStreamResponse(nil, nil, response, nil, nil), responseChan)

core/providers/anthropic/chat.go

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -725,7 +725,7 @@ func (chunk *AnthropicStreamEvent) ToBifrostChatCompletionStream() (*schemas.Bif
725725
Object: "chat.completion.chunk",
726726
Choices: []schemas.BifrostResponseChoice{
727727
{
728-
Index: *chunk.Index,
728+
Index: 0,
729729
ChatStreamResponseChoice: &schemas.ChatStreamResponseChoice{
730730
Delta: &schemas.ChatStreamResponseChoiceDelta{
731731
ToolCalls: []schemas.ChatAssistantMessageToolCall{
@@ -760,7 +760,7 @@ func (chunk *AnthropicStreamEvent) ToBifrostChatCompletionStream() (*schemas.Bif
760760
Object: "chat.completion.chunk",
761761
Choices: []schemas.BifrostResponseChoice{
762762
{
763-
Index: *chunk.Index,
763+
Index: 0,
764764
ChatStreamResponseChoice: &schemas.ChatStreamResponseChoice{
765765
Delta: &schemas.ChatStreamResponseChoiceDelta{
766766
Content: chunk.Delta.Text,
@@ -781,7 +781,7 @@ func (chunk *AnthropicStreamEvent) ToBifrostChatCompletionStream() (*schemas.Bif
781781
Object: "chat.completion.chunk",
782782
Choices: []schemas.BifrostResponseChoice{
783783
{
784-
Index: *chunk.Index,
784+
Index: 0,
785785
ChatStreamResponseChoice: &schemas.ChatStreamResponseChoice{
786786
Delta: &schemas.ChatStreamResponseChoiceDelta{
787787
ToolCalls: []schemas.ChatAssistantMessageToolCall{
@@ -809,7 +809,7 @@ func (chunk *AnthropicStreamEvent) ToBifrostChatCompletionStream() (*schemas.Bif
809809
Object: "chat.completion.chunk",
810810
Choices: []schemas.BifrostResponseChoice{
811811
{
812-
Index: *chunk.Index,
812+
Index: 0,
813813
ChatStreamResponseChoice: &schemas.ChatStreamResponseChoice{
814814
Delta: &schemas.ChatStreamResponseChoiceDelta{
815815
Thought: chunk.Delta.Thinking,

core/providers/bedrock/chat.go

Lines changed: 4 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -187,12 +187,6 @@ func (chunk *BedrockStreamEvent) ToBifrostChatCompletionStream() (*schemas.Bifro
187187
return streamResponse, nil, false
188188

189189
case chunk.Start != nil && chunk.Start.ToolUse != nil:
190-
// Handle tool use start event
191-
contentBlockIndex := 0
192-
if chunk.ContentBlockIndex != nil {
193-
contentBlockIndex = *chunk.ContentBlockIndex
194-
}
195-
196190
toolUseStart := chunk.Start.ToolUse
197191

198192
// Create tool call structure for start event
@@ -206,7 +200,7 @@ func (chunk *BedrockStreamEvent) ToBifrostChatCompletionStream() (*schemas.Bifro
206200
Object: "chat.completion.chunk",
207201
Choices: []schemas.BifrostResponseChoice{
208202
{
209-
Index: contentBlockIndex,
203+
Index: 0,
210204
ChatStreamResponseChoice: &schemas.ChatStreamResponseChoice{
211205
Delta: &schemas.ChatStreamResponseChoiceDelta{
212206
ToolCalls: []schemas.ChatAssistantMessageToolCall{toolCall},
@@ -218,10 +212,7 @@ func (chunk *BedrockStreamEvent) ToBifrostChatCompletionStream() (*schemas.Bifro
218212

219213
return streamResponse, nil, false
220214

221-
case chunk.ContentBlockIndex != nil && chunk.Delta != nil:
222-
// Handle contentBlockDelta event
223-
contentBlockIndex := *chunk.ContentBlockIndex
224-
215+
case chunk.Delta != nil:
225216
switch {
226217
case chunk.Delta.Text != nil:
227218
// Handle text delta
@@ -231,7 +222,7 @@ func (chunk *BedrockStreamEvent) ToBifrostChatCompletionStream() (*schemas.Bifro
231222
Object: "chat.completion.chunk",
232223
Choices: []schemas.BifrostResponseChoice{
233224
{
234-
Index: contentBlockIndex,
225+
Index: 0,
235226
ChatStreamResponseChoice: &schemas.ChatStreamResponseChoice{
236227
Delta: &schemas.ChatStreamResponseChoiceDelta{
237228
Content: &text,
@@ -260,7 +251,7 @@ func (chunk *BedrockStreamEvent) ToBifrostChatCompletionStream() (*schemas.Bifro
260251
Object: "chat.completion.chunk",
261252
Choices: []schemas.BifrostResponseChoice{
262253
{
263-
Index: contentBlockIndex,
254+
Index: 0,
264255
ChatStreamResponseChoice: &schemas.ChatStreamResponseChoice{
265256
Delta: &schemas.ChatStreamResponseChoiceDelta{
266257
ToolCalls: []schemas.ChatAssistantMessageToolCall{toolCall},

core/schemas/account.go

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@ type Key struct {
1414
AzureKeyConfig *AzureKeyConfig `json:"azure_key_config,omitempty"` // Azure-specific key configuration
1515
VertexKeyConfig *VertexKeyConfig `json:"vertex_key_config,omitempty"` // Vertex-specific key configuration
1616
BedrockKeyConfig *BedrockKeyConfig `json:"bedrock_key_config,omitempty"` // AWS Bedrock-specific key configuration
17+
Enabled *bool `json:"enabled,omitempty"` // Whether the key is active (default: true)
1718
}
1819

1920
// AzureKeyConfig represents the Azure-specific configuration.

framework/configstore/tables/key.go

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@ type TableKey struct {
1919
Value string `gorm:"type:text;not null" json:"value"`
2020
ModelsJSON string `gorm:"type:text" json:"-"` // JSON serialized []string
2121
Weight float64 `gorm:"default:1.0" json:"weight"`
22+
Enabled bool `gorm:"default:true" json:"enabled,omitempty"`
2223
CreatedAt time.Time `gorm:"index;not null" json:"created_at"`
2324
UpdatedAt time.Time `gorm:"index;not null" json:"updated_at"`
2425

transports/bifrost-http/lib/config.go

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1383,10 +1383,11 @@ func (c *Config) GetProviderConfigRedacted(provider schemas.ModelProvider) (*con
13831383
redactedConfig.Keys = make([]schemas.Key, len(config.Keys))
13841384
for i, key := range config.Keys {
13851385
redactedConfig.Keys[i] = schemas.Key{
1386-
ID: key.ID,
1387-
Name: key.Name,
1388-
Models: key.Models, // Copy slice reference - read-only so safe
1389-
Weight: key.Weight,
1386+
ID: key.ID,
1387+
Name: key.Name,
1388+
Models: key.Models, // Copy slice reference - read-only so safe
1389+
Weight: key.Weight,
1390+
Enabled: key.Enabled,
13901391
}
13911392

13921393
// Redact API key value

transports/changelog.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
fix: vertex and bedrock usage aggregation improvements for streaming
2+
fix: choice index fixed to 0 for anthropic and bedrock streaming

ui/app/workspace/providers/views/modelProviderKeysTableView.tsx

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@ import { Button } from "@/components/ui/button";
1414
import { CardHeader, CardTitle } from "@/components/ui/card";
1515
import { DropdownMenu, DropdownMenuContent, DropdownMenuItem, DropdownMenuTrigger } from "@/components/ui/dropdownMenu";
1616
import { Table, TableBody, TableCell, TableHead, TableHeader, TableRow } from "@/components/ui/table";
17+
import { Switch } from "@/components/ui/switch";
1718
import { getErrorMessage, useUpdateProviderMutation } from "@/lib/store";
1819
import { ModelProvider } from "@/lib/types/config";
1920
import { cn } from "@/lib/utils";
@@ -104,6 +105,7 @@ export default function ModelProviderKeysTableView({ provider, className }: Prop
104105
<TableRow>
105106
<TableHead>API Key</TableHead>
106107
<TableHead>Weight</TableHead>
108+
<TableHead>Enabled</TableHead>
107109
<TableHead className="text-right"></TableHead>
108110
</TableRow>
109111
</TableHeader>
@@ -128,6 +130,27 @@ export default function ModelProviderKeysTableView({ provider, className }: Prop
128130
<span className="font-mono text-sm">{key.weight}</span>
129131
</div>
130132
</TableCell>
133+
<TableCell>
134+
<Switch
135+
checked={!!key.enabled}
136+
disabled={!hasUpdateProviderAccess}
137+
onCheckedChange={(checked) => {
138+
updateProvider({
139+
...provider,
140+
keys: provider.keys.map((k, i) =>
141+
i === index ? { ...k, enabled: checked } : k
142+
),
143+
})
144+
.unwrap()
145+
.then(() => {
146+
toast.success(`Key ${checked ? "enabled" : "disabled"} successfully`);
147+
})
148+
.catch((err) => {
149+
toast.error("Failed to update key", { description: getErrorMessage(err) });
150+
});
151+
}}
152+
/>
153+
</TableCell>
131154
<TableCell className="text-right">
132155
<div className="flex items-center justify-end space-x-2">
133156
<DropdownMenu>
@@ -141,6 +164,7 @@ export default function ModelProviderKeysTableView({ provider, className }: Prop
141164
onClick={() => {
142165
setShowAddNewKeyDialog({ show: true, keyIndex: index });
143166
}}
167+
disabled={!key.enabled}
144168
>
145169
<PencilIcon className="mr-1 h-4 w-4" />
146170
Edit

0 commit comments

Comments
 (0)