Files
gpt-load/internal/execution/bifrost/executor.go
T

1333 lines
44 KiB
Go

package bifrost
import (
"bytes"
"context"
"crypto/sha256"
"encoding/hex"
"encoding/json"
"errors"
"fmt"
"io"
"math"
"net/http"
"net/url"
"strings"
"time"
"github.com/maximhq/bifrost/core/providers/openai"
"github.com/maximhq/bifrost/core/schemas"
"gpt-load/internal/channel"
"gpt-load/internal/execution"
"gpt-load/internal/parametertrace"
"gpt-load/internal/protocol"
"gpt-load/internal/reasoning"
)
const (
openAIChatPath = "/v1/chat/completions"
defaultRequestBudget = 5 * time.Minute
streamingSDKIdleGuardGrace = time.Second
)
type preparedAttempt struct {
provider schemas.ModelProvider
mode channel.RouteMode
request *schemas.BifrostChatRequest
responsesRequest *schemas.BifrostResponsesRequest
listModelsRequest *schemas.BifrostListModelsRequest
passthrough *schemas.BifrostPassthroughRequest
typedURL string
clientProtocol protocol.Protocol
directKey schemas.Key
secrets []string
}
type unarySDKResult struct {
response *schemas.BifrostChatResponse
err *schemas.BifrostError
}
type streamSDKResult struct {
stream chan *schemas.BifrostStreamChunk
err *schemas.BifrostError
}
// Execute executes one non-streaming attempt.
func (r *Runtime) Execute(parent context.Context, spec execution.AttemptSpec) (result execution.AttemptResult) {
clientParameters := conversionClientParameters(&spec)
prepared, preflightError := r.prepare(spec, false)
if preflightError != nil {
failure := *preflightError
failure.ConversionTrace = preflightConversionTrace(spec, failure, clientParameters)
return failure
}
var appliedReasoning *reasoning.Config
var conversionTrace *parametertrace.Trace
upstreamAPI := preparedUpstreamAPI(prepared, spec)
defer func() {
if result.AppliedReasoning == nil {
result.AppliedReasoning = appliedReasoning
}
if result.ConversionTrace == nil && prepared.mode == channel.RouteConverted {
result.ConversionTrace = finalConversionTrace(clientParameters, conversionTrace)
}
result.UpstreamAPI = upstreamAPI
}()
if prepared.passthrough != nil {
return r.executeNative(parent, spec, prepared)
}
if prepared.responsesRequest != nil {
return r.executeConvertedResponses(parent, spec, prepared)
}
if prepared.listModelsRequest != nil {
return r.executeListModels(parent, spec, prepared)
}
requestContext, requestCancel := boundedRequestContext(parent, spec.Timeouts.Request)
defer requestCancel()
callContext, callCancel := context.WithCancel(requestContext)
defer callCancel()
bifrostContext := r.newSDKContext(callContext, spec, prepared.directKey)
enableConvertedWireCapture(bifrostContext, prepared, clientParameters)
setTypedRequestURL(bifrostContext, prepared.typedURL)
outcomeChannel := make(chan unarySDKResult, 1)
go func() {
response, bifrostError := r.core.ChatCompletionRequest(bifrostContext, prepared.request)
outcomeChannel <- unarySDKResult{response: response, err: bifrostError}
}()
var outcome unarySDKResult
select {
case outcome = <-outcomeChannel:
if requestContext.Err() != nil {
return unaryContextFailure(requestContext, false)
}
case <-callContext.Done():
return unaryContextFailure(requestContext, false)
}
if outcome.err != nil {
captureWireObservation(&outcome.err.ExtraFields.RawRequest, clientParameters, &appliedReasoning, &conversionTrace)
if prepared.mode == channel.RouteConverted {
return convertedUnaryErrorResult(outcome.err, bifrostContext, prepared.secrets)
}
return unaryErrorResult(outcome.err, bifrostContext, prepared.secrets)
}
if outcome.response != nil {
captureWireObservation(&outcome.response.ExtraFields.RawRequest, clientParameters, &appliedReasoning, &conversionTrace)
}
if failure := largeUnaryResponseFailure(bifrostContext); failure != nil {
return *failure
}
if outcome.response == nil {
return attemptedUnaryFailure(execution.ErrorKindInternal, "execution runtime returned no response")
}
body, usageEvidence, err := encodeChatResponse(outcome.response)
if err != nil {
return startedUnaryFailure(
http.StatusOK,
responseHeaders(outcome.response.ExtraFields.ProviderResponseHeaders, bifrostContext, false),
execution.ErrorKindInternal,
"encode upstream response",
)
}
headers := responseHeaders(outcome.response.ExtraFields.ProviderResponseHeaders, bifrostContext, false)
if needsClientModelAlias(spec) {
body, err = rewriteClientResponseModel(spec.ClientProtocol, body, spec.ClientModel)
if err != nil {
return startedUnaryFailure(http.StatusOK, headers, execution.ErrorKindInternal, "rewrite converted response model")
}
}
requestID := upstreamRequestID(headers)
return execution.AttemptResult{
DispatchState: execution.DispatchMaybeSent,
ResponseStarted: true,
StatusCode: http.StatusOK,
Header: headers,
Body: body,
Model: outcome.response.Model,
UpstreamRequestID: requestID,
Usage: usageEvidence,
}
}
// ExecuteStream executes one streaming attempt and emits ordered events synchronously.
func (r *Runtime) ExecuteStream(
parent context.Context,
spec execution.AttemptSpec,
sink execution.StreamSink,
) (result execution.StreamResult) {
if sink == nil {
return notSentStreamFailure(execution.ErrorKindInvalidRequest, "stream sink is required")
}
clientParameters := conversionClientParameters(&spec)
prepared, preflightError := r.prepare(spec, true)
if preflightError != nil {
failure := streamFromAttemptFailure(*preflightError)
failure.ConversionTrace = preflightConversionTrace(spec, *preflightError, clientParameters)
return failure
}
var appliedReasoning *reasoning.Config
var conversionTrace *parametertrace.Trace
upstreamAPI := preparedUpstreamAPI(prepared, spec)
defer func() {
if result.AppliedReasoning == nil {
result.AppliedReasoning = appliedReasoning
}
if result.ConversionTrace == nil && prepared.mode == channel.RouteConverted {
result.ConversionTrace = finalConversionTrace(clientParameters, conversionTrace)
}
result.UpstreamAPI = upstreamAPI
}()
if prepared.passthrough != nil {
return r.executeNativeStream(parent, spec, prepared, sink)
}
if prepared.responsesRequest != nil {
return r.executeConvertedResponsesStream(parent, spec, prepared, sink)
}
requestContext, requestCancel := boundedRequestContext(parent, spec.Timeouts.Request)
defer requestCancel()
callContext, callCancel := context.WithCancel(requestContext)
defer callCancel()
preResponse := startPreResponseGate(callCancel, spec.Timeouts)
defer preResponse.stop()
bifrostContext := r.newStreamingSDKContext(callContext, spec, prepared.directKey)
enableConvertedWireCapture(bifrostContext, prepared, clientParameters)
setTypedRequestURL(bifrostContext, prepared.typedURL)
outcomeChannel := make(chan streamSDKResult, 1)
go func() {
stream, bifrostError := r.core.ChatCompletionStreamRequest(bifrostContext, prepared.request)
outcomeChannel <- streamSDKResult{stream: stream, err: bifrostError}
}()
var outcome streamSDKResult
select {
case outcome = <-outcomeChannel:
if preResponse.expired() || requestContext.Err() != nil {
return streamContextFailure(requestContext, preResponse.expired(), false, nil, "", "", nil)
}
case <-callContext.Done():
return streamContextFailure(requestContext, preResponse.expired(), false, nil, "", "", nil)
}
preResponse.stop()
if outcome.err != nil {
captureWireObservation(&outcome.err.ExtraFields.RawRequest, clientParameters, &appliedReasoning, &conversionTrace)
if prepared.mode == channel.RouteConverted {
return convertedStreamErrorResult(outcome.err, bifrostContext, prepared.secrets, false, 0, nil, "", nil)
}
return streamErrorResult(outcome.err, bifrostContext, prepared.secrets, false, 0, nil, "", nil)
}
if outcome.stream == nil {
return attemptedStreamFailure(execution.ErrorKindInternal, "execution runtime returned no stream")
}
headers := responseHeaders(nil, bifrostContext, true)
requestID := upstreamRequestID(headers)
ready := execution.StreamEvent{
Sequence: 1,
Kind: execution.StreamEventReady,
StatusCode: http.StatusOK,
Header: headers.Clone(),
UpstreamRequestID: requestID,
}
if err := sink(ready); err != nil {
callCancel()
return streamSinkFailure(headers, requestID, "", nil)
}
sequence := uint64(1)
model := ""
var usageEvidence *execution.UsageEvidence
idleTimer := newIdleTimer(spec.Timeouts.StreamIdle)
defer idleTimer.stop()
for {
select {
case <-requestContext.Done():
callCancel()
return streamContextFailure(requestContext, false, true, headers, requestID, model, usageEvidence)
case <-idleTimer.channel():
callCancel()
return streamContextFailure(requestContext, true, true, headers, requestID, model, usageEvidence)
case chunk, open := <-outcome.stream:
idleTimer.pause()
if !open {
if !sdkStreamEndedNormally(bifrostContext) {
return terminatedStreamFailure(headers, requestID, model, usageEvidence)
}
sequence++
if err := sink(execution.StreamEvent{
Sequence: sequence,
Kind: execution.StreamEventData,
Data: []byte("data: [DONE]\n\n"),
}); err != nil {
callCancel()
return streamSinkFailure(headers, requestID, model, usageEvidence)
}
return execution.StreamResult{
DispatchState: execution.DispatchMaybeSent,
ResponseStarted: true,
StatusCode: http.StatusOK,
Header: headers,
Model: model,
UpstreamRequestID: requestID,
Usage: usageEvidence,
}
}
if chunk == nil {
callCancel()
return streamErrorResult(nil, bifrostContext, prepared.secrets, true, http.StatusOK, headers, model, usageEvidence)
}
if chunk.BifrostError != nil {
captureWireObservation(&chunk.BifrostError.ExtraFields.RawRequest, clientParameters, &appliedReasoning, &conversionTrace)
callCancel()
return streamErrorResult(chunk.BifrostError, bifrostContext, prepared.secrets, true, http.StatusOK, headers, model, usageEvidence)
}
if chunk.BifrostChatResponse == nil {
callCancel()
return streamErrorResult(nil, bifrostContext, prepared.secrets, true, http.StatusOK, headers, model, usageEvidence)
}
response := chunk.BifrostChatResponse
captureWireObservation(&response.ExtraFields.RawRequest, clientParameters, &appliedReasoning, &conversionTrace)
if response.Model != "" {
model = response.Model
}
payload, chunkUsage, err := encodeChatResponse(response)
if err != nil {
callCancel()
return streamErrorResult(nil, bifrostContext, prepared.secrets, true, http.StatusOK, headers, model, usageEvidence)
}
if needsClientModelAlias(spec) {
payload, err = rewriteClientResponseModel(spec.ClientProtocol, payload, spec.ClientModel)
if err != nil {
callCancel()
return streamAliasFailure(http.StatusOK, headers, requestID, model, usageEvidence)
}
}
sequence++
if err := sink(execution.StreamEvent{
Sequence: sequence,
Kind: execution.StreamEventData,
Data: frameSSE(payload),
}); err != nil {
callCancel()
return streamSinkFailure(headers, requestID, model, usageEvidence)
}
if chunkUsage != nil {
usageEvidence = cloneUsage(chunkUsage)
sequence++
if err := sink(execution.StreamEvent{
Sequence: sequence,
Kind: execution.StreamEventUsage,
Usage: cloneUsage(chunkUsage),
}); err != nil {
callCancel()
return streamSinkFailure(headers, requestID, model, usageEvidence)
}
}
idleTimer.resume()
}
}
}
func preparedUpstreamAPI(prepared preparedAttempt, spec execution.AttemptSpec) execution.UpstreamAPI {
providerKind := channel.ProviderKind(spec.TargetKind)
switch providerKind {
case channel.ProviderAzureOpenAI:
return execution.UpstreamAPIAzureOpenAI
case channel.ProviderAWSBedrock:
return execution.UpstreamAPIAWSBedrock
case channel.ProviderGoogleVertex:
return execution.UpstreamAPIGoogleVertex
case channel.ProviderAnthropic:
if spec.Operation == execution.OperationListModels {
return execution.UpstreamAPIAnthropicModels
}
return execution.UpstreamAPIAnthropicMessages
case channel.ProviderGemini:
if spec.Operation == execution.OperationListModels {
return execution.UpstreamAPIGeminiModels
}
return execution.UpstreamAPIGeminiGenerateContent
}
if spec.Operation == execution.OperationListModels {
return execution.UpstreamAPIOpenAIModels
}
if prepared.passthrough != nil && spec.ClientProtocol == protocol.OpenAIResponses {
return execution.UpstreamAPIOpenAIResponses
}
if prepared.responsesRequest != nil {
target, err := url.Parse(prepared.typedURL)
if err == nil && strings.HasSuffix(strings.TrimRight(target.Path, "/"), "/responses") {
return execution.UpstreamAPIOpenAIResponses
}
}
return execution.UpstreamAPIOpenAIChatCompletions
}
func (r *Runtime) prepare(spec execution.AttemptSpec, stream bool) (preparedAttempt, *execution.AttemptResult) {
if r == nil || r.core == nil || r.registry == nil {
failure := notSentUnaryFailure(execution.ErrorKindInternal, "execution runtime is unavailable")
return preparedAttempt{}, &failure
}
if r.closed.Load() {
failure := notSentUnaryFailure(execution.ErrorKindInternal, "execution runtime is shut down")
return preparedAttempt{}, &failure
}
if err := spec.Validate(); err != nil {
failure := notSentUnaryFailure(execution.ErrorKindInvalidRequest, "invalid execution attempt: "+safeValidationReason(err))
return preparedAttempt{}, &failure
}
if !supportedRequestShape(spec, stream) {
failure := notSentUnaryFailure(execution.ErrorKindInvalidRequest, "unsupported protocol or operation")
return preparedAttempt{}, &failure
}
channelID := channel.ID(spec.ChannelID)
providerKind := channel.ProviderKind(spec.TargetKind)
if !providerKind.Valid() {
failure := notSentUnaryFailure(execution.ErrorKindInvalidRequest, "unsupported execution target")
return preparedAttempt{}, &failure
}
if len(bytes.TrimSpace(spec.TargetConfig)) == 0 {
failure := notSentUnaryFailure(execution.ErrorKindInvalidRequest, "channel target is required")
return preparedAttempt{}, &failure
}
resolved, err := r.registry.ResolveExecutionTarget(channelID, spec.TargetConfig)
if err != nil {
failure := notSentUnaryFailure(execution.ErrorKindInvalidRequest, "invalid channel target: "+safeValidationReason(err))
return preparedAttempt{}, &failure
}
if resolved.ProviderKind != providerKind {
failure := notSentUnaryFailure(execution.ErrorKindInvalidRequest, "execution target does not match channel")
return preparedAttempt{}, &failure
}
if r.fixedConfig == nil {
failure := notSentUnaryFailure(execution.ErrorKindInternal, "provider runtime config is unavailable")
return preparedAttempt{}, &failure
}
effective, effectiveErr := buildEffectiveProviderConfig(resolved, r.allowPrivate)
if effectiveErr != nil || effective.fingerprint != r.fixedConfig.fingerprint ||
!bytes.Equal(effective.canonical, r.fixedConfig.canonical) {
failure := notSentUnaryFailure(execution.ErrorKindInvalidRequest, "execution target does not match provider runtime")
return preparedAttempt{}, &failure
}
mode := channel.RouteMode(spec.RouteMode)
declaredMode, ok := resolved.Mode(spec.ClientProtocol, spec.Operation)
if !ok || declaredMode != mode {
failure := notSentConversionFailure(
execution.ErrorCodeTargetConversionNotSupported,
"channel does not support the requested route",
)
return preparedAttempt{}, &failure
}
if !spec.RouteRequirement.Allows(execution.RouteMode(mode)) {
failure := notSentConversionFailure(
execution.ErrorCodeCriticalSemanticLoss,
"converted route cannot preserve provider resource semantics",
)
return preparedAttempt{}, &failure
}
if spec.Operation == execution.OperationResponsesCreate &&
spec.RouteRequirement.Normalize() == execution.RouteRequirementNative &&
!resolved.SupportsResponsesLifecycle() {
failure := notSentConversionFailure(
execution.ErrorCodeCriticalSemanticLoss,
"target does not support Responses resource lifecycle",
)
return preparedAttempt{}, &failure
}
if spec.Operation == execution.OperationResponsesPassthrough &&
providerKind != channel.ProviderOpenAI &&
providerKind != channel.ProviderOpenAICompatible {
failure := notSentConversionFailure(
execution.ErrorCodeTargetConversionNotSupported,
"Responses passthrough requires an OpenAI provider",
)
return preparedAttempt{}, &failure
}
provider := r.fixedConfig.provider
targetBaseURL := ""
if r.fixedConfig.custom {
targetBaseURL = r.fixedConfig.targetBaseURL
}
if mode == channel.RouteNative && spec.Operation == execution.OperationListModels &&
!providerKindNativeForClient(providerKind, spec.ClientProtocol) {
failure := notSentConversionFailure(
execution.ErrorCodeTargetConversionNotSupported,
"native route does not match the client protocol",
)
return preparedAttempt{}, &failure
}
safeQuery := safeAttemptQuery(spec)
if providerKind == channel.ProviderGemini {
safeQuery = removeRawQueryValue(safeQuery, "alt")
if stream {
safeQuery = setRawQueryValue(safeQuery, "alt", "sse")
}
}
credential, err := r.registry.ValidateCredential(channelID, spec.Credential.Data())
if err != nil {
failure := notSentUnaryFailure(execution.ErrorKindInvalidRequest, "invalid credential: "+safeValidationReason(err))
return preparedAttempt{}, &failure
}
directKey, secrets, err := directKeyForAttempt(spec, providerKind, spec.TargetConfig, credential)
if err != nil {
failure := notSentUnaryFailure(execution.ErrorKindInvalidRequest, "invalid credential")
return preparedAttempt{}, &failure
}
if spec.Operation == execution.OperationProbe {
request := newProbeRequest(provider, providerKind, spec.UpstreamModel)
responses := spec.ClientProtocol == protocol.OpenAIResponses
typedURL, targetErr := convertedTypedTarget(
providerKind,
targetBaseURL,
spec.UpstreamModel,
responses,
false,
"",
)
if targetErr != nil {
failure := notSentUnaryFailure(execution.ErrorKindInvalidRequest, "invalid channel probe target")
return preparedAttempt{}, &failure
}
prepared := preparedAttempt{
provider: provider, mode: mode, typedURL: typedURL,
clientProtocol: spec.ClientProtocol, directKey: directKey, secrets: secrets,
}
if responses {
prepared.responsesRequest = request.ToResponsesRequest()
} else {
prepared.request = request
}
return prepared, nil
}
if mode == channel.RouteNative && providerSupportsPassthrough(providerKind, targetBaseURL) {
body, err := sanitizeNativeRequestBody(spec, stream)
if err != nil {
failure := notSentUnaryFailure(execution.ErrorKindInvalidRequest, "invalid native request body")
return preparedAttempt{}, &failure
}
passthroughPath, err := nativePassthroughPath(spec, providerKind)
if err != nil {
failure := notSentUnaryFailure(execution.ErrorKindInvalidRequest, "invalid native request path")
return preparedAttempt{}, &failure
}
return preparedAttempt{
provider: provider,
mode: mode,
passthrough: &schemas.BifrostPassthroughRequest{
Provider: provider,
Model: spec.UpstreamModel,
Method: spec.Method,
Path: passthroughPath,
RawQuery: safeQuery,
Body: body,
SafeHeaders: safePassthroughHeaders(spec.Header),
},
directKey: directKey,
secrets: secrets,
}, nil
}
if spec.Operation == execution.OperationListModels {
typedURL, targetErr := convertedListModelsTarget(providerKind, targetBaseURL, safeQuery)
if targetErr != nil {
failure := notSentUnaryFailure(execution.ErrorKindInvalidRequest, "invalid compatible channel target")
return preparedAttempt{}, &failure
}
return preparedAttempt{
provider: provider,
mode: mode,
listModelsRequest: &schemas.BifrostListModelsRequest{Provider: provider},
typedURL: typedURL,
clientProtocol: spec.ClientProtocol,
directKey: directKey,
secrets: secrets,
}, nil
}
if spec.ClientProtocol != protocol.OpenAICompletions || spec.Operation != execution.OperationChatCompletion {
request, conversionErr := buildConvertedResponsesRequest(spec, provider)
if conversionErr != nil {
var classified interface{ ConversionCode() string }
if errors.As(conversionErr, &classified) {
failure := notSentConversionFailure(classified.ConversionCode(), conversionErr.Error())
return preparedAttempt{}, &failure
}
failure := notSentUnaryFailure(execution.ErrorKindInvalidRequest, conversionErr.Error())
return preparedAttempt{}, &failure
}
typedURL, targetErr := convertedTypedTarget(providerKind, targetBaseURL, spec.UpstreamModel, true, stream, safeQuery)
if targetErr != nil {
failure := notSentUnaryFailure(execution.ErrorKindInvalidRequest, "invalid compatible channel target")
return preparedAttempt{}, &failure
}
return preparedAttempt{
provider: provider,
mode: mode,
responsesRequest: request,
typedURL: typedURL,
clientProtocol: spec.ClientProtocol,
directKey: directKey,
secrets: secrets,
}, nil
}
var openAIRequest openai.OpenAIChatRequest
if err := json.Unmarshal(spec.Body, &openAIRequest); err != nil {
failure := notSentUnaryFailure(execution.ErrorKindInvalidRequest, "invalid OpenAI chat request body")
return preparedAttempt{}, &failure
}
conversionContext := schemas.NewBifrostContext(context.Background(), schemas.NoDeadline)
request := openAIRequest.ToBifrostChatRequest(conversionContext)
conversionContext.Cancel()
if request == nil || request.Input == nil {
failure := notSentUnaryFailure(execution.ErrorKindInvalidRequest, "OpenAI chat messages are required")
return preparedAttempt{}, &failure
}
request.Provider = provider
request.Model = spec.UpstreamModel
request.Fallbacks = nil
request.RawRequestBody = nil
if request.Params != nil && request.Params.ExtraParams != nil {
delete(request.Params.ExtraParams, "provider")
delete(request.Params.ExtraParams, "fallback")
delete(request.Params.ExtraParams, "fallbacks")
}
typedURL, err := convertedTypedTarget(providerKind, targetBaseURL, spec.UpstreamModel, false, stream, safeQuery)
if err != nil {
failure := notSentUnaryFailure(execution.ErrorKindInvalidRequest, "invalid compatible channel target")
return preparedAttempt{}, &failure
}
return preparedAttempt{
provider: provider, mode: mode, request: request, typedURL: typedURL,
clientProtocol: spec.ClientProtocol, directKey: directKey, secrets: secrets,
}, nil
}
func newProbeRequest(
provider schemas.ModelProvider,
providerKind channel.ProviderKind,
model string,
) *schemas.BifrostChatRequest {
content := "ping"
params := &schemas.ChatParameters{MaxCompletionTokens: schemas.Ptr(1)}
if providerKind == channel.ProviderOpenAICompatible {
params.MaxCompletionTokens = nil
params.ExtraParams = map[string]any{"max_tokens": 1}
}
return &schemas.BifrostChatRequest{
Provider: provider,
Model: model,
Input: []schemas.ChatMessage{{
Role: schemas.ChatMessageRoleUser,
Content: &schemas.ChatMessageContent{
ContentStr: &content,
},
}},
Params: params,
}
}
func providerSupportsPassthrough(providerKind channel.ProviderKind, baseURL string) bool {
switch providerKind {
case channel.ProviderOpenAI, channel.ProviderAnthropic, channel.ProviderGemini:
return true
case channel.ProviderOpenAICompatible:
// Bifrost v1.7.7's OpenAI passthrough always inserts /v1. A compatible
// full API prefix with another suffix must use the typed custom path,
// without changing the frozen route mode or channel capability.
return strings.HasSuffix(baseURL, "/v1")
default:
return false
}
}
func providerKindNativeForClient(providerKind channel.ProviderKind, clientProtocol protocol.Protocol) bool {
switch providerKind {
case channel.ProviderOpenAI, channel.ProviderOpenAICompatible:
return clientProtocol == protocol.OpenAICompletions || clientProtocol == protocol.OpenAIResponses
case channel.ProviderAnthropic:
return clientProtocol == protocol.Anthropic
case channel.ProviderGemini:
return clientProtocol == protocol.Gemini
case channel.ProviderDeepSeek, channel.ProviderOpenRouter, channel.ProviderGroq, channel.ProviderXAI:
return clientProtocol == protocol.OpenAICompletions || clientProtocol == protocol.OpenAIResponses
default:
return false
}
}
func supportedRequestShape(spec execution.AttemptSpec, stream bool) bool {
if spec.Operation == execution.OperationListModels {
if stream || spec.Method != http.MethodGet {
return false
}
switch spec.ClientProtocol {
case protocol.OpenAICompletions, protocol.OpenAIResponses, protocol.Anthropic:
return spec.Path == "/v1/models"
case protocol.Gemini:
return spec.Path == "/v1beta/models"
default:
return false
}
}
if spec.Operation == execution.OperationProbe {
if stream || strings.TrimSpace(spec.UpstreamModel) == "" || spec.Method != "" ||
spec.Path != "" || len(spec.Query) != 0 || spec.RawQuery != "" || len(spec.Body) != 0 {
return false
}
switch spec.ClientProtocol {
case protocol.OpenAICompletions, protocol.OpenAIResponses, protocol.Anthropic, protocol.Gemini:
return true
default:
return false
}
}
switch spec.ClientProtocol {
case protocol.OpenAICompletions:
return spec.Operation == execution.OperationChatCompletion &&
spec.Method == http.MethodPost && spec.Path == openAIChatPath
case protocol.OpenAIResponses:
switch spec.Operation {
case execution.OperationResponsesCreate:
return spec.Method == http.MethodPost && spec.Path == "/v1/responses"
case execution.OperationResponsesRetrieve:
return spec.Method == http.MethodGet && validResponsesResourcePath(spec.Path, "")
case execution.OperationResponsesDelete:
return !stream && spec.Method == http.MethodDelete && validResponsesResourcePath(spec.Path, "")
case execution.OperationResponsesCancel:
return !stream && spec.Method == http.MethodPost && validResponsesResourcePath(spec.Path, "cancel")
case execution.OperationResponsesInputItems:
return !stream && spec.Method == http.MethodGet && validResponsesResourcePath(spec.Path, "input_items")
case execution.OperationResponsesCompact:
return !stream && spec.Method == http.MethodPost && spec.Path == "/v1/responses/compact"
case execution.OperationResponsesInputTokens:
return !stream && spec.Method == http.MethodPost && spec.Path == "/v1/responses/input_tokens"
case execution.OperationResponsesPassthrough:
return validResponsesPassthroughShape(spec, stream)
}
case protocol.Anthropic:
return spec.Operation == execution.OperationChatCompletion && spec.Method == http.MethodPost && spec.Path == "/v1/messages"
case protocol.Gemini:
if spec.Operation != execution.OperationChatCompletion || spec.Method != http.MethodPost {
return false
}
action := "generateContent"
if stream {
action = "streamGenerateContent"
}
return validGeminiGeneratePath(spec.Path, action)
}
return false
}
func validResponsesPassthroughShape(spec execution.AttemptSpec, stream bool) bool {
remainder, ok := strings.CutPrefix(spec.Path, "/v1/responses/")
if !ok || remainder == "" {
return false
}
switch spec.Method {
case http.MethodOptions, http.MethodConnect, http.MethodTrace:
return false
case http.MethodHead:
return !stream
default:
return true
}
}
func validGeminiGeneratePath(path, action string) bool {
prefix := "/v1beta/models/"
remainder, ok := strings.CutPrefix(path, prefix)
if !ok {
return false
}
model, suffix, ok := strings.Cut(remainder, ":")
return ok && suffix == action && validResourceID(model) && !strings.Contains(model, "/")
}
func nativePassthroughPath(spec execution.AttemptSpec, providerKind channel.ProviderKind) (string, error) {
switch providerKind {
case channel.ProviderOpenAI, channel.ProviderOpenAICompatible:
return spec.Path, nil
case channel.ProviderAnthropic:
return spec.Path, nil
case channel.ProviderGemini:
path, ok := strings.CutPrefix(spec.Path, "/v1beta")
if !ok || path == "" {
return "", fmt.Errorf("invalid Gemini path")
}
if spec.Operation == execution.OperationListModels {
if path != "/models" {
return "", fmt.Errorf("invalid Gemini models path")
}
return path, nil
}
marker := "/models/"
modelStart := strings.Index(path, marker)
colon := strings.LastIndex(path, ":")
if modelStart < 0 || colon <= modelStart+len(marker) {
return "", fmt.Errorf("invalid Gemini model path")
}
return path[:modelStart+len(marker)] + url.PathEscape(spec.UpstreamModel) + path[colon:], nil
default:
return "", fmt.Errorf("unsupported native channel")
}
}
func validResponsesResourcePath(path, action string) bool {
remainder, ok := strings.CutPrefix(path, "/v1/responses/")
if !ok || remainder == "" {
return false
}
parts := strings.Split(remainder, "/")
if action == "" {
return len(parts) == 1 && validResourceID(parts[0])
}
return len(parts) == 2 && validResourceID(parts[0]) && parts[1] == action
}
func validResourceID(value string) bool {
return value != "" && value != "." && value != ".." && !strings.ContainsAny(value, "\\?#")
}
func customProviderKey(baseProvider schemas.ModelProvider, baseURL string) schemas.ModelProvider {
digest := sha256.Sum256([]byte(string(baseProvider) + "\x00" + baseURL))
return schemas.ModelProvider("gptload-custom-" + hex.EncodeToString(digest[:]))
}
func directKeyForAttempt(
spec execution.AttemptSpec,
providerKind channel.ProviderKind,
targetConfig json.RawMessage,
credential channel.Credential,
) (schemas.Key, []string, error) {
key := schemas.Key{
ID: fmt.Sprintf("%d:%d:%d", spec.Credential.ID, spec.Credential.IdentityGeneration, spec.Credential.Version),
Name: "selected credential",
Models: schemas.WhiteList{"*"},
Weight: 1,
}
secrets := credentialSecrets(credential)
apiKey, _ := credential.Value("api_key")
switch providerKind {
case channel.ProviderOpenAI, channel.ProviderAnthropic, channel.ProviderGemini,
channel.ProviderDeepSeek, channel.ProviderOpenRouter, channel.ProviderGroq, channel.ProviderXAI,
channel.ProviderOpenAICompatible:
if apiKey == "" {
return schemas.Key{}, nil, fmt.Errorf("api_key is required")
}
key.Value = plainSecret(apiKey)
case channel.ProviderAzureOpenAI:
var target struct {
Endpoint string `json:"endpoint"`
}
if json.Unmarshal(targetConfig, &target) != nil || target.Endpoint == "" {
return schemas.Key{}, nil, fmt.Errorf("azure endpoint is required")
}
key.AzureKeyConfig = &schemas.AzureKeyConfig{Endpoint: plainSecret(target.Endpoint)}
if apiKey != "" {
key.Value = plainSecret(apiKey)
} else {
clientID, clientOK := credential.Value("client_id")
clientSecret, secretOK := credential.Value("client_secret")
tenantID, tenantOK := credential.Value("tenant_id")
if !clientOK || !secretOK || !tenantOK {
return schemas.Key{}, nil, fmt.Errorf("complete Entra credentials are required")
}
key.AzureKeyConfig.ClientID = plainSecretPtr(clientID)
key.AzureKeyConfig.ClientSecret = plainSecretPtr(clientSecret)
key.AzureKeyConfig.TenantID = plainSecretPtr(tenantID)
}
case channel.ProviderAWSBedrock:
var target struct {
Region string `json:"region"`
}
if json.Unmarshal(targetConfig, &target) != nil || target.Region == "" {
return schemas.Key{}, nil, fmt.Errorf("Bedrock region is required")
}
config := &schemas.BedrockKeyConfig{Region: plainSecretPtr(target.Region)}
if apiKey != "" {
key.Value = plainSecret(apiKey)
} else {
if value, ok := credential.Value("access_key"); ok {
config.AccessKey = plainSecret(value)
}
if value, ok := credential.Value("secret_key"); ok {
config.SecretKey = plainSecret(value)
}
config.SessionToken = optionalPlainSecret(credential, "session_token")
config.RoleARN = optionalPlainSecret(credential, "role_arn")
config.ExternalID = optionalPlainSecret(credential, "external_id")
config.RoleSessionName = optionalPlainSecret(credential, "session_name")
}
key.BedrockKeyConfig = config
case channel.ProviderGoogleVertex:
var target struct {
ProjectID string `json:"project_id"`
ProjectNumber string `json:"project_number"`
Location string `json:"location"`
}
if json.Unmarshal(targetConfig, &target) != nil || target.ProjectID == "" || target.Location == "" {
return schemas.Key{}, nil, fmt.Errorf("Vertex project and location are required")
}
serviceAccount, ok := credential.Value("service_account_json")
if !ok || serviceAccount == "" {
return schemas.Key{}, nil, fmt.Errorf("Vertex service account is required")
}
key.VertexKeyConfig = &schemas.VertexKeyConfig{
ProjectID: plainSecret(target.ProjectID),
ProjectNumber: plainSecret(target.ProjectNumber),
Region: plainSecret(target.Location),
AuthCredentials: plainSecret(serviceAccount),
}
default:
return schemas.Key{}, nil, fmt.Errorf("unsupported provider kind")
}
return key, secrets, nil
}
func plainSecret(value string) schemas.SecretVar {
return schemas.SecretVar{Val: value, SecretType: schemas.SecretTypePlainText}
}
func plainSecretPtr(value string) *schemas.SecretVar {
secret := plainSecret(value)
return &secret
}
func optionalPlainSecret(credential channel.Credential, field string) *schemas.SecretVar {
value, ok := credential.Value(field)
if !ok || value == "" {
return nil
}
return plainSecretPtr(value)
}
func credentialSecrets(credential channel.Credential) []string {
fields := []string{
"api_key", "client_id", "client_secret", "tenant_id", "access_key", "secret_key",
"session_token", "role_arn", "external_id", "session_name", "service_account_json",
}
seen := make(map[string]struct{}, len(fields))
result := make([]string, 0, len(fields))
appendSecret := func(value string) {
if value == "" {
return
}
if _, exists := seen[value]; exists {
return
}
seen[value] = struct{}{}
result = append(result, value)
}
for _, field := range fields {
value, ok := credential.Value(field)
if !ok {
continue
}
appendSecret(value)
if field == "service_account_json" {
var object map[string]json.RawMessage
if json.Unmarshal([]byte(value), &object) == nil {
for _, nestedField := range []string{"private_key", "private_key_id", "client_email"} {
var nested string
if json.Unmarshal(object[nestedField], &nested) == nil {
appendSecret(nested)
}
}
}
}
}
return result
}
func (r *Runtime) newSDKContext(parent context.Context, spec execution.AttemptSpec, directKey schemas.Key) *schemas.BifrostContext {
bifrostContext := schemas.NewBifrostContext(parent, schemas.NoDeadline)
bifrostContext.SetValue(schemas.BifrostContextKeyRequestID, spec.RequestID)
bifrostContext.SetValue(schemas.BifrostContextKeyDirectKey, directKey)
bifrostContext.SetValue(schemas.BifrostContextKeyLargeResponseThreshold, r.maxUnaryResponseBodyBytes)
if spec.Operation == execution.OperationProbe &&
channel.ProviderKind(spec.TargetKind) == channel.ProviderOpenAICompatible {
bifrostContext.SetValue(schemas.BifrostContextKeyPassthroughExtraParams, true)
}
if spec.Timeouts.StreamIdle > 0 {
bifrostContext.SetValue(schemas.BifrostContextKeyStreamIdleTimeout, spec.Timeouts.StreamIdle)
}
if headers := safeRequestHeaders(spec.Header); len(headers) > 0 {
bifrostContext.SetValue(schemas.BifrostContextKeyExtraHeaders, headers)
}
return bifrostContext
}
func (r *Runtime) newStreamingSDKContext(parent context.Context, spec execution.AttemptSpec, directKey schemas.Key) *schemas.BifrostContext {
bifrostContext := r.newSDKContext(parent, spec, directKey)
if spec.Timeouts.StreamIdle > 0 {
// GPT-Load owns the user-facing chunk deadline; Bifrost remains a later raw-read backstop.
bifrostContext.SetValue(
schemas.BifrostContextKeyStreamIdleTimeout,
streamingSDKIdleGuard(spec.Timeouts.StreamIdle),
)
}
return bifrostContext
}
func streamingSDKIdleGuard(configured time.Duration) time.Duration {
maximum := time.Duration(math.MaxInt64)
if configured > maximum-streamingSDKIdleGuardGrace {
return maximum
}
return configured + streamingSDKIdleGuardGrace
}
func largeUnaryResponseFailure(bifrostContext *schemas.BifrostContext) *execution.AttemptResult {
if bifrostContext == nil {
return nil
}
large, _ := bifrostContext.Value(schemas.BifrostContextKeyLargeResponseMode).(bool)
if !large {
return nil
}
if reader, ok := bifrostContext.Value(schemas.BifrostContextKeyLargeResponseReader).(io.Closer); ok && reader != nil {
_ = reader.Close()
}
headers := responseHeaders(nil, bifrostContext, false)
result := startedUnaryFailure(
http.StatusOK,
headers,
execution.ErrorKindInternal,
"upstream response exceeds size limit",
)
return &result
}
func safeRequestHeaders(source http.Header) map[string][]string {
if len(source) == 0 {
return nil
}
result := make(map[string][]string)
for name, values := range source {
canonical := http.CanonicalHeaderKey(name)
if !safeUpstreamRequestHeader(canonical) {
continue
}
result[canonical] = append([]string(nil), values...)
}
return result
}
func safePassthroughHeaders(source http.Header) map[string]string {
if len(source) == 0 {
return nil
}
result := make(map[string]string)
for name, values := range source {
canonical := http.CanonicalHeaderKey(name)
if !safeUpstreamRequestHeader(canonical) || len(values) == 0 {
continue
}
result[canonical] = strings.Join(values, ", ")
}
return result
}
func safeUpstreamQuery(source url.Values) url.Values {
if len(source) == 0 {
return nil
}
result := make(url.Values)
for key, values := range source {
if unsafeUpstreamQueryKey(key) {
continue
}
result[key] = append([]string(nil), values...)
}
return result
}
func safeRawUpstreamQuery(source string) string {
if source == "" {
return ""
}
segments := strings.Split(source, "&")
kept := make([]string, 0, len(segments))
for _, segment := range segments {
key := segment
if separator := strings.IndexByte(key, '='); separator >= 0 {
key = key[:separator]
}
if decoded, err := url.QueryUnescape(key); err == nil {
key = decoded
}
if unsafeUpstreamQueryKey(key) {
continue
}
kept = append(kept, segment)
}
return strings.Join(kept, "&")
}
func safeAttemptQuery(spec execution.AttemptSpec) string {
if spec.RawQuery != "" {
return safeRawUpstreamQuery(spec.RawQuery)
}
return safeUpstreamQuery(spec.Query).Encode()
}
func unsafeUpstreamQueryKey(key string) bool {
normalized := strings.ReplaceAll(strings.ToLower(key), "-", "_")
switch normalized {
case "provider", "fallback", "fallbacks", "authorization", "proxy_authorization",
"api_key", "apikey", "x_api_key", "x_goog_api_key", "key", "access_token":
return true
default:
return false
}
}
func resolveTypedTargetURL(baseURL, resourcePath, rawQuery string) (string, error) {
parsed, err := url.Parse(baseURL)
if err != nil || parsed == nil || !parsed.IsAbs() || parsed.Host == "" || parsed.User != nil || parsed.Fragment != "" {
return "", fmt.Errorf("invalid target URL")
}
parsed.Path = strings.TrimRight(parsed.Path, "/") + resourcePath
parsed.RawPath = ""
if rawQuery != "" {
parsed.RawQuery = rawQuery
}
return parsed.String(), nil
}
func setTypedRequestURL(ctx *schemas.BifrostContext, requestURL string) {
if ctx != nil && requestURL != "" {
ctx.SetValue(schemas.BifrostContextKeyURLPath, requestURL)
}
}
func safeUpstreamRequestHeader(canonical string) bool {
switch canonical {
case "Authorization", "Proxy-Authorization", "Api-Key", "X-Api-Key", "X-Goog-Api-Key",
"Host", "Content-Length", "Connection", "Proxy-Connection", "Keep-Alive", "Te", "Trailer",
"Transfer-Encoding", "Upgrade", "Cookie", "Set-Cookie":
return false
}
return !strings.HasPrefix(strings.ToLower(canonical), "x-bf-")
}
func boundedRequestContext(parent context.Context, budget time.Duration) (context.Context, context.CancelFunc) {
if parent == nil {
parent = context.Background()
}
if budget > 0 {
return context.WithTimeout(parent, budget)
}
if _, hasDeadline := parent.Deadline(); hasDeadline {
return context.WithCancel(parent)
}
// Bifrost's fasthttp operation may outlive a canceled caller while it releases
// pooled objects. A finite default keeps that SDK cleanup goroutine bounded.
return context.WithTimeout(parent, defaultRequestBudget)
}
type responseGate struct {
timer *time.Timer
fired chan struct{}
stopOne chan struct{}
}
func startPreResponseGate(cancel context.CancelFunc, timeouts execution.AttemptTimeouts) *responseGate {
budget := timeouts.FirstByte
gate := &responseGate{fired: make(chan struct{}), stopOne: make(chan struct{})}
if budget <= 0 {
return gate
}
// Core exposes neither an independent dial hook nor transport configuration
// per attempt. This gate is therefore used only where the adapter can observe
// a native response or complete client stream frame. Buffered converted unary
// calls are bounded by Request instead of mislabeling body time as first byte.
gate.timer = time.AfterFunc(budget, func() {
select {
case <-gate.stopOne:
return
default:
}
close(gate.fired)
cancel()
})
return gate
}
func (g *responseGate) stop() {
if g == nil {
return
}
select {
case <-g.stopOne:
return
default:
close(g.stopOne)
}
if g.timer != nil {
g.timer.Stop()
}
}
func (g *responseGate) expired() bool {
if g == nil {
return false
}
select {
case <-g.fired:
return true
default:
return false
}
}
func minimumPositive(values ...time.Duration) time.Duration {
var result time.Duration
for _, value := range values {
if value > 0 && (result == 0 || value < result) {
result = value
}
}
return result
}
type streamIdleTimer struct {
duration time.Duration
timer *time.Timer
ch <-chan time.Time
}
func newIdleTimer(duration time.Duration) *streamIdleTimer {
timer := &streamIdleTimer{duration: duration}
if duration > 0 {
timer.timer = time.NewTimer(duration)
timer.ch = timer.timer.C
}
return timer
}
func (t *streamIdleTimer) channel() <-chan time.Time {
if t == nil {
return nil
}
return t.ch
}
func (t *streamIdleTimer) pause() {
if t == nil || t.timer == nil {
return
}
if !t.timer.Stop() {
select {
case <-t.timer.C:
default:
}
}
t.ch = nil
}
func (t *streamIdleTimer) resume() {
if t == nil || t.timer == nil {
return
}
t.timer.Reset(t.duration)
t.ch = t.timer.C
}
func (t *streamIdleTimer) stop() {
if t != nil {
t.pause()
}
}
func safeValidationReason(err error) string {
if err == nil {
return "validation failed"
}
message := strings.TrimSpace(err.Error())
if message == "" || strings.ContainsAny(message, "\r\n\x00") {
return "validation failed"
}
if len(message) > 192 {
return message[:192]
}
return message
}
func unaryContextFailure(ctx context.Context, preResponseExpired bool) execution.AttemptResult {
kind, summary := contextFailure(ctx, preResponseExpired)
return attemptedUnaryFailure(kind, summary)
}
func streamContextFailure(
ctx context.Context,
preResponseExpired bool,
started bool,
headers http.Header,
requestID string,
model string,
usageEvidence *execution.UsageEvidence,
) execution.StreamResult {
kind, summary := contextFailure(ctx, preResponseExpired)
if !started {
return attemptedStreamFailure(kind, summary)
}
return execution.StreamResult{
DispatchState: execution.DispatchMaybeSent,
ResponseStarted: true,
StatusCode: http.StatusOK,
Header: headers.Clone(),
Model: model,
UpstreamRequestID: requestID,
Usage: cloneUsage(usageEvidence),
Error: &execution.ErrorEvidence{Kind: kind, Summary: summary, RequestID: requestID},
}
}
func contextFailure(ctx context.Context, preResponseExpired bool) (execution.ErrorKind, string) {
if preResponseExpired || errors.Is(ctx.Err(), context.DeadlineExceeded) {
return execution.ErrorKindTimeout, "upstream request timed out"
}
return execution.ErrorKindCanceled, "upstream request canceled"
}
func sdkStreamEndedNormally(ctx *schemas.BifrostContext) bool {
if ctx == nil {
return false
}
ended, _ := ctx.Value(schemas.BifrostContextKeyStreamEndIndicator).(bool)
return ended
}
func terminatedStreamFailure(
headers http.Header,
requestID string,
model string,
usageEvidence *execution.UsageEvidence,
) execution.StreamResult {
return execution.StreamResult{
DispatchState: execution.DispatchMaybeSent,
ResponseStarted: true,
StatusCode: http.StatusOK,
Header: headers.Clone(),
Model: model,
UpstreamRequestID: requestID,
Usage: cloneUsage(usageEvidence),
Error: &execution.ErrorEvidence{
Kind: execution.ErrorKindTransport,
Summary: "upstream stream terminated before completion",
RequestID: requestID,
},
}
}