Skip to content
Merged

v1.5.5 #3771

Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
46 commits
Select commit Hold shift + click to select a range
d8e88d3
feat(governance): add virtual key blocked models (#3653)
Vaibhav701161 May 21, 2026
e662266
v1.5.4 cut (#3680)
akshaydeo May 21, 2026
ef5815b
fix: update e2e ui tests (#3687)
sammaji May 22, 2026
08b42d6
fix: updates mcp oauth api tests (#3693)
sammaji May 22, 2026
ce639e1
feat: add timeout comments to guardrail rule and provider entries in …
BearTS May 25, 2026
927e921
feat: add optional gRPC port to bifrost cluster deployment and servic…
BearTS May 25, 2026
a197486
fix: use `REDISCLI_AUTH` env var to avoid passing password via `-a` f…
BearTS May 25, 2026
ffe7907
fix: gate Weaviate PVC creation on `persistence.enabled` (#3619)
BearTS May 25, 2026
02b854c
feat: add default password warnings for PostgreSQL and Redis in Helm …
BearTS May 25, 2026
893511b
fix: sort provider secrets and weaviate env vars alphabetically for d…
BearTS May 25, 2026
894bbf7
feat: support `existingSecret` for internal PostgreSQL auth in Bifros…
BearTS May 25, 2026
4171b0c
feat: add configurable pod and container security contexts to postgre…
BearTS May 25, 2026
3fe5a28
chore: bump Bifrost Helm chart to 2.1.18 with feature flags, model ca…
BearTS May 25, 2026
1f509c8
fix: bedrock chat converter reasoning messages closes #3688 (#3690)
TejasGhatte May 25, 2026
3afab61
fix: stop reason with structured output tools (#3685)
TejasGhatte May 25, 2026
90953be
fix: search content and video getting dropped from Bedrock requests (…
roroghost17 May 25, 2026
1fe613c
feat: starts forwarding x-bf-eh to OTEL (#3730)
roroghost17 May 25, 2026
6a84315
docs: adds docs for OTEL on OSS features list and examples (#3731)
roroghost17 May 25, 2026
3de6b87
refactor: changes attribute keys in OTEL plugin to follow semantic co…
roroghost17 May 25, 2026
0586177
fix: set ConnectionClosed flag before closing stream on cancellation …
TejasGhatte May 25, 2026
a222faf
chore: fix bedrock transport tests (#3735)
TejasGhatte May 25, 2026
1d99f0b
refactor(governance): use slices for vk blocklist matching (#3727)
Vaibhav701161 May 25, 2026
cc9cbe3
fix: allows for toggling non-auth users for MCP temp tokens (#3720)
roroghost17 May 25, 2026
4f7486d
chore: add harness test for auth enabled (#3728)
roroghost17 May 25, 2026
5d2707a
feat: include `ProviderConfigs` with budgets and rate limits in virtu…
BearTS May 25, 2026
3089bfb
fix: fix the path check for temp token (#3737)
roroghost17 May 25, 2026
454102f
adds cleanup flow for logging plugin (#3717)
akshaydeo May 26, 2026
4e43c86
feat: add `ConfigMarshallerPlugin` interface and `EnvVar` support for…
BearTS May 26, 2026
714a7ca
feat: add Kafka as an enterprise observability connector (#3713)
BearTS May 26, 2026
0696803
feat: add Google Cloud Pub/Sub connector view to observability plugin…
BearTS May 26, 2026
22faa46
docs: document `env.VAR_NAME` support for `collector_url`, `metrics_e…
BearTS May 26, 2026
b800eca
feat: migrate azure to v1 api (#3661)
TejasGhatte May 26, 2026
c24a622
chore: remove api version references from code (#3756)
TejasGhatte May 26, 2026
9e74ed3
fix(governance): restore vk blocked models create/edit UI (#3750)
Vaibhav701161 May 26, 2026
7f09b46
fix: skip empty text block in bedrock (#3747)
TejasGhatte May 26, 2026
3242316
chore: bump Bifrost Helm chart to 2.1.19 with bug fixes and changelog…
BearTS May 26, 2026
0e9ae3a
fix: strip cache point from bedrock requests for models which do not …
TejasGhatte May 26, 2026
cb21b66
feat: add responses stream in json parser plugin (#3749)
TejasGhatte May 26, 2026
06991bb
fix: fixes streaming latency for observability by deferring EndSpan (…
roroghost17 May 26, 2026
d997936
test fixes (#3761)
TejasGhatte May 26, 2026
172702d
fix: exclude empty model entries from model rankings matview queries …
impoiler May 26, 2026
7af45ed
refactor: propagate errors from `GetAvailable*` methods instead of si…
impoiler May 26, 2026
731a311
refactor: export `ResolvePeriod` function for external use (#3763)
impoiler May 26, 2026
4a7363d
fix: recreate `mv_filter_users` matview to exclude rows with empty `u…
impoiler May 26, 2026
5e4bfb7
v1.5.5 changelog (#3769)
akshaydeo May 26, 2026
0891e20
dac, access profiles, tool groups docs (#3738)
akshaydeo May 26, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
50 changes: 49 additions & 1 deletion .github/workflows/scripts/run-migration-tests.sh
Original file line number Diff line number Diff line change
Expand Up @@ -1750,6 +1750,29 @@ append_dynamic_columns_postgres() {
echo "UPDATE mcp_tool_logs SET business_unit_id = NULL WHERE id = 'mcp-log-migration-001';" >> "$output_file"
echo "UPDATE mcp_tool_logs SET business_unit_id = NULL WHERE id = 'mcp-log-migration-002';" >> "$output_file"
fi

# -------------------------------------------------------------------------
# v1.5.4 columns
# -------------------------------------------------------------------------

# governance_virtual_key_provider_configs.blacklisted_models (added in v1.5.4 via migrationAddVirtualKeyBlacklistedModelsColumn)
if column_exists_postgres "governance_virtual_key_provider_configs" "blacklisted_models"; then
echo "UPDATE governance_virtual_key_provider_configs SET blacklisted_models = '[]' WHERE virtual_key_id = 'vk-migration-test-1';" >> "$output_file"
echo "UPDATE governance_virtual_key_provider_configs SET blacklisted_models = '[]' WHERE virtual_key_id = 'vk-migration-test-2';" >> "$output_file"
fi

# governance_virtual_keys.created_by_user_id (added in v1.5.4 via migrationAddCreatedByUserIDColumnForVirtualKeys)
if column_exists_postgres "governance_virtual_keys" "created_by_user_id"; then
echo "UPDATE governance_virtual_keys SET created_by_user_id = NULL WHERE id = 'vk-migration-test-1';" >> "$output_file"
echo "UPDATE governance_virtual_keys SET created_by_user_id = NULL WHERE id = 'vk-migration-test-2';" >> "$output_file"
fi

# logs.inc_number (added in v1.5.4 via migrationAddLogIncNumberColumn)
if column_exists_postgres "logs" "inc_number"; then
echo "UPDATE logs SET inc_number = NULL WHERE id = 'log-migration-test-001';" >> "$output_file"
echo "UPDATE logs SET inc_number = NULL WHERE id = 'log-migration-test-002';" >> "$output_file"
echo "UPDATE logs SET inc_number = NULL WHERE id = 'log-migration-test-003';" >> "$output_file"
fi
}

# Append dynamic column UPDATEs for columns that may not exist in older schemas (SQLite)
Expand Down Expand Up @@ -2702,6 +2725,30 @@ append_dynamic_columns_sqlite() {
# mcp_tool_logs.business_unit_id (added in v1.5.3 via migrationAddGovernanceColumnsToMCPToolLogs)
echo "UPDATE mcp_tool_logs SET business_unit_id = NULL WHERE id = 'mcp-log-migration-001';" >> "$output_file"
echo "UPDATE mcp_tool_logs SET business_unit_id = NULL WHERE id = 'mcp-log-migration-002';" >> "$output_file"

# -------------------------------------------------------------------------
# v1.5.4 columns
# -------------------------------------------------------------------------

if [ -f "$config_db" ]; then
# governance_virtual_key_provider_configs.blacklisted_models (added in v1.5.4 via migrationAddVirtualKeyBlacklistedModelsColumn)
if column_exists_sqlite "$config_db" "governance_virtual_key_provider_configs" "blacklisted_models"; then
echo "UPDATE governance_virtual_key_provider_configs SET blacklisted_models = '[]' WHERE virtual_key_id = 'vk-migration-test-1';" >> "$output_file"
echo "UPDATE governance_virtual_key_provider_configs SET blacklisted_models = '[]' WHERE virtual_key_id = 'vk-migration-test-2';" >> "$output_file"
fi

# governance_virtual_keys.created_by_user_id (added in v1.5.4 via migrationAddCreatedByUserIDColumnForVirtualKeys)
if column_exists_sqlite "$config_db" "governance_virtual_keys" "created_by_user_id"; then
echo "UPDATE governance_virtual_keys SET created_by_user_id = NULL WHERE id = 'vk-migration-test-1';" >> "$output_file"
echo "UPDATE governance_virtual_keys SET created_by_user_id = NULL WHERE id = 'vk-migration-test-2';" >> "$output_file"
fi
fi

# logs.inc_number (added in v1.5.4 via migrationAddLogIncNumberColumn)
# Emitted unconditionally - logs table is in logs_db; fails silently on config_db
echo "UPDATE logs SET inc_number = NULL WHERE id = 'log-migration-test-001';" >> "$output_file"
echo "UPDATE logs SET inc_number = NULL WHERE id = 'log-migration-test-002';" >> "$output_file"
echo "UPDATE logs SET inc_number = NULL WHERE id = 'log-migration-test-003';" >> "$output_file"
}

# ============================================================================
Expand Down Expand Up @@ -3838,8 +3885,9 @@ compare_postgres_snapshots() {
fi
# azure_deployments_json, vertex_deployments_json, bedrock_deployments_json, replicate_deployments_json
# (dropped from config_keys - migrated to provider-level deployment config)
# azure_api_version (dropped from config_keys in v1.5.4 via migrationDropAzureAPIVersionColumn)
if [ "$table" = "config_keys" ]; then
dropped_columns="$dropped_columns azure_deployments_json vertex_deployments_json bedrock_deployments_json replicate_deployments_json"
dropped_columns="$dropped_columns azure_deployments_json vertex_deployments_json bedrock_deployments_json replicate_deployments_json azure_api_version"
fi
# budget_id (dropped from governance_virtual_keys and governance_virtual_key_provider_configs
# in add_multi_budget_tables - ownership moved to governance_budgets.virtual_key_id/provider_config_id)
Expand Down
81 changes: 63 additions & 18 deletions core/bifrost.go
Original file line number Diff line number Diff line change
Expand Up @@ -4573,7 +4573,8 @@ func (bifrost *Bifrost) handleRequest(ctx *schemas.BifrostContext, req *schemas.
// Start span for fallback attempt
tracer := bifrost.getTracer()
spanCtx, handle := tracer.StartSpan(ctx, fmt.Sprintf("fallback.%s.%s", fallback.Provider, fallback.Model), schemas.SpanKindFallback)
tracer.SetAttribute(handle, schemas.AttrProviderName, string(fallback.Provider))
tracer.SetAttribute(handle, schemas.AttrProviderName, schemas.OTelProviderName(fallback.Provider))
tracer.SetAttribute(handle, schemas.AttrBifrostProviderName, string(fallback.Provider)) // raw Bifrost short name, mirrors canonical gen_ai.provider.name
tracer.SetAttribute(handle, schemas.AttrRequestModel, fallback.Model)
tracer.SetAttribute(handle, "fallback.index", i+1)
ctx.SetValue(schemas.BifrostContextKeySpanID, spanCtx.Value(schemas.BifrostContextKeySpanID))
Expand Down Expand Up @@ -4654,7 +4655,8 @@ func (bifrost *Bifrost) handleStreamRequest(ctx *schemas.BifrostContext, req *sc
// Start span for fallback attempt
tracer := bifrost.getTracer()
spanCtx, handle := tracer.StartSpan(ctx, fmt.Sprintf("fallback.%s.%s", fallback.Provider, fallback.Model), schemas.SpanKindFallback)
tracer.SetAttribute(handle, schemas.AttrProviderName, string(fallback.Provider))
tracer.SetAttribute(handle, schemas.AttrProviderName, schemas.OTelProviderName(fallback.Provider))
tracer.SetAttribute(handle, schemas.AttrBifrostProviderName, string(fallback.Provider)) // raw Bifrost short name, mirrors canonical gen_ai.provider.name
tracer.SetAttribute(handle, schemas.AttrRequestModel, fallback.Model)
tracer.SetAttribute(handle, "fallback.index", i+1)
ctx.SetValue(schemas.BifrostContextKeySpanID, spanCtx.Value(schemas.BifrostContextKeySpanID))
Expand Down Expand Up @@ -5268,10 +5270,11 @@ func executeRequestWithRetries[T any](
var keyHandle schemas.SpanHandle
if keyTracer != nil {
keySpanCtx, keyHandle = keyTracer.StartSpan(ctx, "key.selection", schemas.SpanKindInternal)
keyTracer.SetAttribute(keyHandle, schemas.AttrProviderName, string(providerKey))
keyTracer.SetAttribute(keyHandle, schemas.AttrProviderName, schemas.OTelProviderName(providerKey))
keyTracer.SetAttribute(keyHandle, schemas.AttrBifrostProviderName, string(providerKey)) // raw Bifrost short name, mirrors canonical gen_ai.provider.name
keyTracer.SetAttribute(keyHandle, schemas.AttrRequestModel, model)
if attempts > 0 {
keyTracer.SetAttribute(keyHandle, "retry.count", attempts)
keyTracer.SetAttribute(keyHandle, schemas.AttrLegacyRetryCount, attempts)
}
}

Expand Down Expand Up @@ -5341,50 +5344,92 @@ func executeRequestWithRetries[T any](
}
var spanName string
var spanKind schemas.SpanKind
otelOp := schemas.OTelOperationName(requestType)
if attempts > 0 {
spanName = fmt.Sprintf("retry.attempt.%d", attempts)
spanKind = schemas.SpanKindRetry
} else {
spanName = "llm.call"
// Span name format per OTel GenAI semconv: "{operation} {model}".
spanName = fmt.Sprintf("%s %s", otelOp, model)
spanKind = schemas.SpanKindLLMCall
}
spanCtx, handle := tracer.StartSpan(ctx, spanName, spanKind)
tracer.SetAttribute(handle, schemas.AttrProviderName, string(providerKey))
tracer.SetAttribute(handle, schemas.AttrProviderName, schemas.OTelProviderName(providerKey))
tracer.SetAttribute(handle, schemas.AttrBifrostProviderName, string(providerKey)) // raw Bifrost short name, mirrors canonical gen_ai.provider.name
tracer.SetAttribute(handle, schemas.AttrRequestModel, model)
tracer.SetAttribute(handle, "request.type", string(requestType))
tracer.SetAttribute(handle, schemas.AttrOperationName, otelOp)
tracer.SetAttribute(handle, schemas.AttrLegacyRequestType, string(requestType)) // legacy: replaced by gen_ai.operation.name
if attempts > 0 {
tracer.SetAttribute(handle, "retry.count", attempts)
tracer.SetAttribute(handle, schemas.AttrLegacyRetryCount, attempts) // legacy: bare key with no semconv prefix
}

// Add context-related attributes (selected key, virtual key, team, customer, etc.)
// Each AttrXxx (gen_ai.*) emission below is LEGACY namespace pollution: the
// Bifrost-internal concept does not belong under gen_ai.*. The bifrost.* mirrors
// are the canonical home going forward; once all dashboards migrate, drop the
// gen_ai.* lines (grep for "// legacy:" in this block).
if selectedKeyID, ok := ctx.Value(schemas.BifrostContextKeySelectedKeyID).(string); ok && selectedKeyID != "" {
tracer.SetAttribute(handle, schemas.AttrSelectedKeyID, selectedKeyID)
tracer.SetAttribute(handle, schemas.AttrSelectedKeyID, selectedKeyID) // legacy: gen_ai.* placement of bifrost-internal attr
tracer.SetAttribute(handle, schemas.AttrBifrostSelectedKeyID, selectedKeyID)
}
if selectedKeyName, ok := ctx.Value(schemas.BifrostContextKeySelectedKeyName).(string); ok && selectedKeyName != "" {
tracer.SetAttribute(handle, schemas.AttrSelectedKeyName, selectedKeyName)
tracer.SetAttribute(handle, schemas.AttrSelectedKeyName, selectedKeyName) // legacy: gen_ai.* placement of bifrost-internal attr
tracer.SetAttribute(handle, schemas.AttrBifrostSelectedKeyName, selectedKeyName)
}
if virtualKeyID, ok := ctx.Value(schemas.BifrostContextKeyGovernanceVirtualKeyID).(string); ok && virtualKeyID != "" {
tracer.SetAttribute(handle, schemas.AttrVirtualKeyID, virtualKeyID)
tracer.SetAttribute(handle, schemas.AttrVirtualKeyID, virtualKeyID) // legacy: gen_ai.* placement of bifrost-internal attr
tracer.SetAttribute(handle, schemas.AttrBifrostVirtualKeyID, virtualKeyID)
}
if virtualKeyName, ok := ctx.Value(schemas.BifrostContextKeyGovernanceVirtualKeyName).(string); ok && virtualKeyName != "" {
tracer.SetAttribute(handle, schemas.AttrVirtualKeyName, virtualKeyName)
tracer.SetAttribute(handle, schemas.AttrVirtualKeyName, virtualKeyName) // legacy: gen_ai.* placement of bifrost-internal attr
tracer.SetAttribute(handle, schemas.AttrBifrostVirtualKeyName, virtualKeyName)
}
if teamID, ok := ctx.Value(schemas.BifrostContextKeyGovernanceTeamID).(string); ok && teamID != "" {
tracer.SetAttribute(handle, schemas.AttrTeamID, teamID)
tracer.SetAttribute(handle, schemas.AttrTeamID, teamID) // legacy: gen_ai.* placement of bifrost-internal attr
tracer.SetAttribute(handle, schemas.AttrBifrostTeamID, teamID)
}
if teamName, ok := ctx.Value(schemas.BifrostContextKeyGovernanceTeamName).(string); ok && teamName != "" {
tracer.SetAttribute(handle, schemas.AttrTeamName, teamName)
tracer.SetAttribute(handle, schemas.AttrTeamName, teamName) // legacy: gen_ai.* placement of bifrost-internal attr
tracer.SetAttribute(handle, schemas.AttrBifrostTeamName, teamName)
}
if customerID, ok := ctx.Value(schemas.BifrostContextKeyGovernanceCustomerID).(string); ok && customerID != "" {
tracer.SetAttribute(handle, schemas.AttrCustomerID, customerID)
tracer.SetAttribute(handle, schemas.AttrCustomerID, customerID) // legacy: gen_ai.* placement of bifrost-internal attr
tracer.SetAttribute(handle, schemas.AttrBifrostCustomerID, customerID)
}
if customerName, ok := ctx.Value(schemas.BifrostContextKeyGovernanceCustomerName).(string); ok && customerName != "" {
tracer.SetAttribute(handle, schemas.AttrCustomerName, customerName)
tracer.SetAttribute(handle, schemas.AttrCustomerName, customerName) // legacy: gen_ai.* placement of bifrost-internal attr
tracer.SetAttribute(handle, schemas.AttrBifrostCustomerName, customerName)
}
if fallbackIndex, ok := ctx.Value(schemas.BifrostContextKeyFallbackIndex).(int); ok {
tracer.SetAttribute(handle, schemas.AttrFallbackIndex, fallbackIndex)
tracer.SetAttribute(handle, schemas.AttrFallbackIndex, fallbackIndex) // legacy: gen_ai.* placement of bifrost-internal attr
tracer.SetAttribute(handle, schemas.AttrBifrostFallbackIndex, fallbackIndex)
}
tracer.SetAttribute(handle, schemas.AttrNumberOfRetries, attempts) // legacy: gen_ai.* placement of bifrost-internal attr
tracer.SetAttribute(handle, schemas.AttrBifrostRetries, attempts)

// Surface caller-supplied extra headers (from x-bf-eh-* and direct-allowlist
// header forwarding) as span attributes so observability backends see the
// same set Bifrost forwards to the upstream provider.
if extraHeaders, ok := ctx.Value(schemas.BifrostContextKeyExtraHeaders).(map[string][]string); ok {
for name, values := range extraHeaders {
if name == "" || len(values) == 0 {
continue
}
// Never export credential-bearing headers verbatim. The transport
// layer denylists most sensitive headers, but plain authorization /
// set-cookie can still reach here, and core SDK callers bypass that
// guard entirely. Keep the key (presence is useful) but redact the value.
if schemas.IsSensitiveHeader(name) {
tracer.SetAttribute(handle, schemas.AttrExtraHeaderPrefix+name, schemas.RedactedAttrValue)
continue
}
if len(values) == 1 {
tracer.SetAttribute(handle, schemas.AttrExtraHeaderPrefix+name, values[0])
} else {
tracer.SetAttribute(handle, schemas.AttrExtraHeaderPrefix+name, values)
}
}
}
tracer.SetAttribute(handle, schemas.AttrNumberOfRetries, attempts)

// Populate LLM request attributes (messages, parameters, etc.)
if req != nil {
Expand Down
14 changes: 14 additions & 0 deletions core/changelog.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
- feat: migrate Azure provider to the v1 API and remove `api_version` from `AzureKeyConfig` (#3661, #3756)
- feat: add `ConfigMarshallerPlugin` interface so plugins can control config storage and redaction round-trips (#3651)
- feat: forward `x-bf-eh-*` extra headers as `gen_ai.request.extra_header.*` span attributes (#3730)
- feat: align OTel attribute keys with the GenAI semantic conventions spec; emit both legacy and canonical attributes (#3732)
- fix: strip cache points from Bedrock requests for models that do not support prompt caching (#3754)
- fix: skip empty/nil text blocks during Bedrock response conversion (#3747)
- fix: preserve reasoning blocks alongside tool calls in the Bedrock chat converter (#3690)
- fix: restore search content and video parts dropped from Bedrock passthrough requests (#3729)
- fix: correct `tool_calls` finish reason when structured output is combined with extended-thinking tools (#3685)
- fix: set `BifrostContextKeyConnectionClosed` before closing stream and short-circuit `idleTimeoutReader.Read` on closed connections (#3733)
- fix: Gemini tool schema passthrough via `parametersJsonSchema`, correct tool response role to `user`, resolve structured output + tools conflict (#3761)
- fix: normalize Anthropic stop reason mapping and upgrade computer-use tool versions to `text_editor_20250728` (#3761)
- fix: Azure config redaction panic when `Endpoint` is a literal value (#3761)
- chore: fix Bedrock transport tests (#3735)
4 changes: 1 addition & 3 deletions core/internal/llmtests/account.go
Original file line number Diff line number Diff line change
Expand Up @@ -311,7 +311,6 @@ func (account *ComprehensiveTestAccount) GetKeysForProvider(ctx context.Context,
},
AzureKeyConfig: &schemas.AzureKeyConfig{
Endpoint: *schemas.NewEnvVar("env.AZURE_ENDPOINT"),
APIVersion: schemas.NewEnvVar("env.AZURE_API_VERSION"),
ClientID: schemas.NewEnvVar("env.AZURE_CLIENT_ID"),
ClientSecret: schemas.NewEnvVar("env.AZURE_CLIENT_SECRET"),
TenantID: schemas.NewEnvVar("env.AZURE_TENANT_ID"),
Expand All @@ -329,8 +328,7 @@ func (account *ComprehensiveTestAccount) GetKeysForProvider(ctx context.Context,
"gpt-4o-mini-audio-preview": "gpt-4o-mini-audio-preview",
},
AzureKeyConfig: &schemas.AzureKeyConfig{
Endpoint: *schemas.NewEnvVar("env.AZURE_ENDPOINT"),
APIVersion: schemas.NewEnvVar("env.AZURE_API_VERSION"),
Endpoint: *schemas.NewEnvVar("env.AZURE_ENDPOINT"),
},
},
}, nil
Expand Down
15 changes: 9 additions & 6 deletions core/internal/llmtests/passthrough_api.go
Original file line number Diff line number Diff line change
Expand Up @@ -66,9 +66,11 @@ func buildPassthroughChatReq(t *testing.T, provider schemas.ModelProvider, model
if err != nil {
t.Fatalf("azure: failed to marshal passthrough chat request: %v", err)
}
// Azure passthrough expects the deployment-based path; api-version is
// injected automatically by buildPassthroughURL from the key config.
return passthroughChatReq{path: fmt.Sprintf("/openai/deployments/%s/chat/completions", model), body: body}, true
return passthroughChatReq{
path: fmt.Sprintf("/openai/deployments/%s/chat/completions", model),
body: body,
query: "api-version=2025-04-01-preview",
}, true

case schemas.Anthropic:
nativeReq, err := anthropic.ToAnthropicChatRequest(ctx, bfReq)
Expand Down Expand Up @@ -158,9 +160,10 @@ func RunPassthroughAPITest(t *testing.T, client *bifrost.Bifrost, ctx context.Co
bfCtx := schemas.NewBifrostContext(ctx, schemas.NoDeadline)

resp, bifrostErr := client.Passthrough(bfCtx, testConfig.Provider, &schemas.BifrostPassthroughRequest{
Method: "POST",
Path: req.path,
Body: req.body,
Method: "POST",
Path: req.path,
Body: req.body,
RawQuery: req.query,
SafeHeaders: map[string]string{
"content-type": "application/json",
},
Expand Down
Loading
Loading