package gateway import ( "context" "encoding/json" "fmt" "io" "net/http" "strings" "time" "gpt-load/internal/dialect" "gpt-load/internal/execution" platformheader "gpt-load/internal/platform/httpheader" "gpt-load/internal/platform/redact" "gpt-load/internal/protocol" "gpt-load/internal/usage" ) // ExecutionForwarder adapts the provider-neutral executor to the gateway's // downstream commit boundary while the handler orchestration remains intact. type ExecutionForwarder struct { executor execution.Executor representation *responseProcessor usageCapture *usageCaptureBoundary writeTimeout time.Duration } func NewExecutionForwarder(executor execution.Executor) *ExecutionForwarder { return &ExecutionForwarder{ executor: executor, representation: &responseProcessor{redactor: redact.New()}, usageCapture: newUsageCaptureBoundary(), writeTimeout: downstreamWriteTimeout, } } func (forwarder *ExecutionForwarder) OpenWebsocket(ctx context.Context, input ForwardInput) (execution.WebsocketSession, execution.WebsocketResult) { spec, err := newExecutionAttemptSpec(input) if forwarder != nil && err == nil { if opener, ok := forwarder.executor.(execution.WebsocketOpener); ok { return opener.OpenWebsocket(ctx, spec) } } return nil, execution.WebsocketResult{DispatchState: execution.DispatchNotSent, Error: &execution.ErrorEvidence{ Kind: execution.ErrorKindInvalidRequest, OriginHint: execution.ErrorOriginInternal, ScopeHint: execution.ErrorScopeRequest, Code: "websocket_not_supported", Summary: "Native WebSocket is not supported.", }} } func (forwarder *ExecutionForwarder) Forward( ctx context.Context, input ForwardInput, ) UpstreamResult { spec, err := newExecutionAttemptSpec(input) if err != nil || forwarder == nil || forwarder.executor == nil { return executionInputFailure(err) } executionResult := forwarder.executor.Execute(ctx, spec) if err := executionResult.Validate(); err != nil { return invalidExecutionAttemptResult(executionResult) } result := upstreamFromExecutionResult(ctx, input, executionResult) result = forwarder.prepareBufferedResult(input, result) if (input.ClientProtocol == protocol.OpenAIImages || input.ClientProtocol == protocol.OpenAIEmbeddings || input.ClientProtocol == protocol.Rerank) && input.ObserveUsage && result.HasResponse() && result.StatusCode >= http.StatusOK && result.StatusCode < http.StatusMultipleChoices && executionResult.Usage == nil && result.Usage.State == usage.StateMissing && forwarder.usageCapture != nil { result.Usage = forwarder.usageCapture.extractNonStreamingPlain( input.Dialect, result.ClassificationBody, ) } if input.ClientProtocol == protocol.OpenAIEmbeddings && result.Err == nil && result.StatusCode >= http.StatusOK && result.StatusCode < http.StatusMultipleChoices { result.ClassificationBody = nil } return result } func invalidExecutionAttemptResult(result execution.AttemptResult) UpstreamResult { dispatchState := execution.DispatchNotSent if result.DispatchState == execution.DispatchLocal { dispatchState = execution.DispatchLocal } else if result.DispatchState == execution.DispatchMaybeSent || result.ResponseStarted || result.StatusCode != 0 || len(result.Header) > 0 || len(result.Body) > 0 { dispatchState = execution.DispatchMaybeSent } evidence := execution.ErrorEvidence{ Kind: execution.ErrorKindInternal, OriginHint: execution.ErrorOriginInternal, ScopeHint: execution.ErrorScopeRequest, Code: "attempt_result_contract_invalid", Summary: "Attempt executor returned an invalid result.", ReplaySafety: execution.ReplaySafetyUnknown, } return UpstreamResult{ Err: fmt.Errorf("%w: invalid attempt executor result", ErrUpstreamProtocol), RequestWritten: dispatchState == execution.DispatchMaybeSent, DispatchState: dispatchState, ExecutionError: &evidence, ErrorSummary: evidence.Summary, Usage: usage.Result{State: usage.StateNotApplicable}, } } func (forwarder *ExecutionForwarder) ForwardStream( ctx context.Context, input ForwardInput, downstream http.ResponseWriter, ) UpstreamResult { spec, err := newExecutionAttemptSpec(input) if err != nil || forwarder == nil || forwarder.executor == nil || downstream == nil { return executionInputFailure(err) } writeTimeout := forwarder.writeTimeout if writeTimeout <= 0 { writeTimeout = downstreamWriteTimeout } controller := newStreamWriteController(downstream, writeTimeout) defer func() { _ = controller.clear() }() usageCapture := forwarder.usageCapture if usageCapture == nil { usageCapture = newUsageCaptureBoundary() } streamEvents := newStreamEventObserver( input.Dialect, usageCapture.newStreamForRequest(input.Dialect, input.ObserveUsage), ) redactor := redact.New() if forwarder.representation != nil && forwarder.representation.redactor != nil { redactor = forwarder.representation.redactor } summarySecrets := resolvedErrorSummarySecretValues( input.APIKey, input.Group.HeaderRules, input.CredentialSecrets..., ) credentialSecrets := append([]string(nil), input.CredentialSecrets...) if input.APIKey != "" { credentialSecrets = append(credentialSecrets, input.APIKey) } streamBuffer := newSSEEventObservationBuffer(execution.SSEEventLimit(input.ClientProtocol), func( event dialect.StreamEvent, genericProviderError bool, ) (bool, error) { if input.ClientProtocol == protocol.OpenAIImages && imagesCredentialLiteralsRemain(event.Payload, credentialSecrets) { return false, fmt.Errorf("%w: credential remains in response event", ErrUpstreamProtocol) } wasTerminal := streamEvents.sawTerminal providerError, err := streamEvents.classify(event, genericProviderError) if err != nil { return false, err } if !wasTerminal && !providerError && input.OnResponse != nil { object, err := decodeResponsesStoreObject(event.Payload) if err != nil { return false, err } if response, exists := object["response"]; exists { if err := input.OnResponse(response); err != nil { return false, err } } } if !wasTerminal { streamEvents.observeUsageEvent(event) if providerError { streamEvents.observeError( event.Payload, summarizeErrorBody( redactor, event.Payload, fixedErrorSummary("upstream_sse_error"), summarySecrets..., ), ) } } return !wasTerminal && streamEvents.sawTerminal, nil }) var responsesStoreBuffer *statelessResponsesSSEBuffer if input.ResponsesStoreDowngraded { responsesStoreBuffer = newStatelessResponsesSSEBuffer() } var ( ready *execution.StreamEvent committed bool firstResponse bool downstreamErr error errorBody []byte streamUsage *execution.UsageEvidence ) sink := func(event execution.StreamEvent) error { if err := event.Validate(); err != nil { downstreamErr = fmt.Errorf("%w: invalid execution stream event", ErrUpstreamProtocol) return downstreamErr } switch event.Kind { case execution.StreamEventReady: copy := event.Clone() if copy.StatusCode >= http.StatusOK && copy.StatusCode < http.StatusMultipleChoices { if err := validateStreamContentEncoding(copy.Header); err != nil { downstreamErr = err return err } copy.Header = normalizeStreamResponseHeaders( sanitizeForwardResponseHeaders(copy.Header, input), ) } else { copy.Header = sanitizeForwardResponseHeaders(copy.Header, input) } ready = © return nil case execution.StreamEventUsage: if event.Usage != nil { copy := event.Usage.Clone() streamUsage = © } return nil case execution.StreamEventData: if ready == nil { downstreamErr = fmt.Errorf("%w: execution data arrived before response metadata", ErrUpstreamProtocol) return downstreamErr } if ready.StatusCode < http.StatusOK || ready.StatusCode >= http.StatusMultipleChoices { errorBody = appendExecutionErrorBody(errorBody, event.Data) return nil } observedData := event.Data if responsesStoreBuffer != nil { observedData, err = responsesStoreBuffer.push(event.Data) if err != nil { downstreamErr = executionStreamProtocolFailure(err) return downstreamErr } if len(observedData) == 0 { return nil } } completeData, terminalInChunk, err := streamBuffer.push(observedData) if err != nil { downstreamErr = executionStreamProtocolFailure(err) return downstreamErr } forwardData := observedData if input.ClientProtocol == protocol.OpenAIImages || responsesStoreBuffer != nil || input.OnResponse != nil { forwardData = completeData if len(forwardData) == 0 { return nil } } if !committed { if !firstResponse { firstResponse = true if input.OnFirstResponse != nil { input.OnFirstResponse() } } if streamEvents.firstEventWasProviderError() { errorBody = appendExecutionErrorBody(errorBody, forwardData) return nil } committed = true if err := commitStream(controller, ready.StatusCode, ready.Header, forwardData); err != nil { downstreamErr = err return err } if input.OnStreamReady != nil { input.OnStreamReady() } if terminalInChunk { streamEvents.markTerminalForwarded() } return nil } written, err := controller.write(forwardData) if err != nil { downstreamErr = &streamFailure{ kind: streamFailureDownstreamWrite, err: fmt.Errorf("write execution stream: %w", err), } return downstreamErr } if written != len(forwardData) { downstreamErr = &streamFailure{ kind: streamFailureDownstreamWrite, err: fmt.Errorf("write execution stream: %w", io.ErrShortWrite), } return downstreamErr } if err := controller.flush(); err != nil { downstreamErr = &streamFailure{ kind: streamFailureDownstreamWrite, err: fmt.Errorf("flush execution stream: %w", err), } return downstreamErr } if terminalInChunk { streamEvents.markTerminalForwarded() } return nil default: downstreamErr = fmt.Errorf("%w: unsupported execution stream event", ErrUpstreamProtocol) return downstreamErr } } terminal := forwarder.executor.ExecuteStream(ctx, spec, sink) if err := terminal.Validate(); err != nil { terminal = invalidExecutionStreamResult(terminal, ready, committed) } if downstreamErr == nil && terminal.Error == nil { if responsesStoreBuffer != nil { if err := responsesStoreBuffer.finish(); err != nil { downstreamErr = executionStreamProtocolFailure(err) } } if downstreamErr == nil { if err := streamBuffer.finish(); err != nil { downstreamErr = executionStreamProtocolFailure(err) } else if err := streamEvents.validateEOF(); err != nil { downstreamErr = err } } } capturedUsage := streamEvents.finalizeUsage() result := upstreamFromExecutionStreamResult(ctx, input, terminal, streamUsage) if input.ObserveUsage && input.ClientProtocol == protocol.Anthropic && input.RouteMode == execution.RouteNative && capturedUsage.State != usage.StateMissing { // 原生 Anthropic 流以实际事件为用量依据。SDK 的最大值合并会丢失 // 输入修正、明确的零、缓存 TTL 明细,以及流是否完整结束的信息。 result.Usage = capturedUsage } else { // 未采集到用量时,保留执行层已经取得的证据。 result.Usage = preferCapturedStreamUsage(result.Usage, capturedUsage) } result.Committed = committed if len(errorBody) > 0 { result.Body = append([]byte(nil), errorBody...) result.ClassificationBody = append([]byte(nil), errorBody...) } if downstreamErr != nil { result.Err = downstreamErr } if committed { result.Stream = executionStreamObservation(ctx, terminal, downstreamErr, streamEvents) } else if ready != nil { result.StatusCode = ready.StatusCode result.Header = ready.Header.Clone() result.ResponseStarted = true result.UpstreamRequestID = ready.UpstreamRequestID } if !committed && streamEvents.firstEventWasProviderError() { summary := streamEvents.firstSummary if summary == "" { summary = fixedErrorSummary("upstream_sse_error") } result.ProviderErrorBeforeCommit = true result.ErrorSummary = summary result.ExecutionError = firstStreamErrorEvidence( streamEvents.firstErrorPayload, result.ExecutionError, result.StatusCode, result.UpstreamRequestID, summary, redactor, summarySecrets, ) } if !committed && result.HasResponse() && !result.ProviderErrorBeforeCommit { result = forwarder.prepareBufferedResult(input, result) } return result } func invalidExecutionStreamResult( result execution.StreamResult, ready *execution.StreamEvent, committed bool, ) execution.StreamResult { dispatchState := execution.DispatchNotSent if result.DispatchState == execution.DispatchLocal && !committed && ready == nil { dispatchState = execution.DispatchLocal } else if committed || ready != nil || result.DispatchState == execution.DispatchMaybeSent || result.ResponseStarted || result.StatusCode != 0 || len(result.Header) > 0 { dispatchState = execution.DispatchMaybeSent } normalized := execution.StreamResult{DispatchState: dispatchState} if ready != nil { normalized.ResponseStarted = true normalized.StatusCode = ready.StatusCode normalized.Header = ready.Header.Clone() normalized.UpstreamRequestID = ready.UpstreamRequestID } evidence := execution.ErrorEvidence{ Kind: execution.ErrorKindInternal, OriginHint: execution.ErrorOriginInternal, ScopeHint: execution.ErrorScopeRequest, Code: "attempt_result_contract_invalid", Summary: "Attempt executor returned an invalid result.", ReplaySafety: execution.ReplaySafetyUnknown, } if normalized.ResponseStarted { evidence.StatusCode = normalized.StatusCode } normalized.Error = &evidence return normalized } func firstStreamErrorEvidence( payload []byte, existing *execution.ErrorEvidence, statusCode int, requestID string, summary string, redactor *redact.Redactor, knownSecrets []string, ) *execution.ErrorEvidence { evidence := execution.ErrorEvidence{ Kind: execution.ErrorKindProvider, StatusCode: statusCode, Summary: summary, RequestID: requestID, } if existing != nil { evidence = existing.Clone() evidence.Kind = execution.ErrorKindProvider if evidence.StatusCode == 0 { evidence.StatusCode = statusCode } if evidence.Summary == "" { evidence.Summary = summary } if evidence.RequestID == "" { evidence.RequestID = requestID } } type errorObject struct { Type string `json:"type"` Code json.RawMessage `json:"code"` Status string `json:"status"` Message string `json:"message"` } var envelope struct { Type string `json:"type"` Code json.RawMessage `json:"code"` Error errorObject `json:"error"` Response struct { Error errorObject `json:"error"` } `json:"response"` } if json.Unmarshal(payload, &envelope) != nil { return &evidence } providerError := envelope.Error if providerError.Type == "" && len(providerError.Code) == 0 && providerError.Status == "" && providerError.Message == "" { providerError = envelope.Response.Error } typeValue := providerError.Type if typeValue == "" && !strings.EqualFold(envelope.Type, "error") { typeValue = envelope.Type } codeValue := streamErrorEvidenceScalar(providerError.Code) if codeValue == "" { codeValue = streamErrorEvidenceScalar(envelope.Code) } if codeValue == "" { codeValue = providerError.Status } typeValue = sanitizeStreamErrorEvidenceValue(redactor, typeValue, knownSecrets) codeValue = sanitizeStreamErrorEvidenceValue(redactor, codeValue, knownSecrets) statusValue := sanitizeStreamErrorEvidenceValue(redactor, providerError.Status, knownSecrets) if evidence.Type == "" { evidence.Type = typeValue } if evidence.Code == "" { evidence.Code = codeValue } if evidence.Hint == "" { evidence.Hint = streamErrorFailureHint( statusCode, typeValue, codeValue, statusValue, evidence.Summary, ) } evidence.OriginHint = execution.ErrorOriginUpstream switch evidence.Hint { case execution.FailureHintInvalidCredential, execution.FailureHintRefreshRequired, execution.FailureHintReauthorizationRequired: evidence.ScopeHint = execution.ErrorScopeCredential case execution.FailureHintModelUnavailable, execution.FailureHintCandidateUnavailable: evidence.ScopeHint = execution.ErrorScopeModel case execution.FailureHintRequestRejected: evidence.ScopeHint = execution.ErrorScopeRequest case execution.FailureHintHostError: evidence.ScopeHint = execution.ErrorScopeGroup } if evidence.ReplaySafety == "" && streamBootstrapCapacityRejection(evidence.Code) { evidence.ReplaySafety = execution.ReplaySafetyRejectedBeforeProcessing } return &evidence } func streamBootstrapCapacityRejection(codeValue string) bool { codeValue = strings.ToLower(strings.TrimSpace(codeValue)) return codeValue == "server_is_overloaded" || codeValue == "rate_limit_exceeded" } func streamErrorEvidenceScalar(value json.RawMessage) string { value = json.RawMessage(strings.TrimSpace(string(value))) if len(value) == 0 || string(value) == "null" { return "" } var text string if json.Unmarshal(value, &text) == nil { return text } var number json.Number if json.Unmarshal(value, &number) == nil { return number.String() } return "" } func sanitizeStreamErrorEvidenceValue( redactor *redact.Redactor, value string, knownSecrets []string, ) string { value = sanitizeErrorSummary(redactor, value, knownSecrets...) const maxEvidenceRunes = 128 runes := []rune(value) if len(runes) > maxEvidenceRunes { return string(runes[:maxEvidenceRunes]) } return value } func streamErrorFailureHint(statusCode int, values ...string) execution.FailureHint { markers := strings.ToLower(strings.Join(values, " ")) switch { case statusCode == http.StatusUnauthorized: return execution.FailureHintInvalidCredential case containsStreamErrorMarker(markers, "model_not_found", "model not found", "model_not_available", "model unavailable", "deployment_not_found", "unsupported_model"): return execution.FailureHintModelUnavailable case statusCode == http.StatusTooManyRequests || containsStreamErrorMarker(markers, "rate_limit", "rate limit", "too_many_requests", "quota_exceeded", "resource_exhausted", "throttl"): return execution.FailureHintRateLimited case containsStreamErrorMarker(markers, "invalid_api_key", "api_key_invalid", "authentication_error", "authentication failed", "invalid credential", "api key not valid"): return execution.FailureHintInvalidCredential case statusCode >= http.StatusInternalServerError && statusCode <= 599: return execution.FailureHintHostError default: return "" } } func containsStreamErrorMarker(value string, markers ...string) bool { for _, marker := range markers { if strings.Contains(value, marker) { return true } } return false } func (forwarder *ExecutionForwarder) prepareBufferedResult( input ForwardInput, result UpstreamResult, ) UpstreamResult { if forwarder == nil || !result.HasResponse() { return result } if input.Operation == execution.OperationWebSearch && result.ProviderErrorBeforeCommit { return result } representation := forwarder.representation if representation == nil { representation = &responseProcessor{redactor: redact.New()} } secrets := append([]string(nil), input.CredentialSecrets...) if input.APIKey != "" { secrets = append(secrets, input.APIKey) } if result.StatusCode >= http.StatusOK && result.StatusCode < http.StatusMultipleChoices { policy := classifyResponseBody(input.Request.Method, result.StatusCode) if !policy.readBody { if err := validateStreamContentEncoding(result.Header); err != nil || (result.StatusCode == http.StatusPartialContent && !hasSafeHeadContentRange(result.Header)) { return executionRepresentationFailure(result, fmt.Errorf("%w: invalid bodyless response representation", ErrUpstreamProtocol)) } headers := sanitizeForwardResponseHeaders(result.Header, input, secrets...) headers, _ = normalizeBufferedResponse(input.Request.Method, result.StatusCode, headers, nil) result.Header = headers result.Body = nil return result } prepared, err := representation.prepareSuccessRepresentation( input, result.StatusCode, result.Header, result.Body, secrets, ) if err != nil { return executionRepresentationFailure(result, err) } result.Header = prepared.headers result.Body = prepared.downstream result.ClassificationBody = prepared.inspectable return result } if result.ExecutionError != nil && (input.RouteMode == execution.RouteConverted || len(result.Body) == 0) { result.Body = encodeClientErrorBody(input.ClientProtocol, result.StatusCode, *result.ExecutionError) result.Header = result.Header.Clone() if result.Header == nil { result.Header = make(http.Header) } deleteHeaderField(result.Header, "Content-Encoding") deleteHeaderField(result.Header, "Content-Length") invalidateRewrittenBodyHeaders(result.Header) result.Header.Set("Content-Type", "application/json") } prepared := representation.prepareErrorRepresentation(input, result.Header, result.Body, secrets) result.Header = prepared.headers result.Body = prepared.downstream result.ClassificationBody = prepared.classification return result } func encodeClientErrorBody( clientProtocol protocol.Protocol, status int, evidence execution.ErrorEvidence, ) []byte { message := strings.TrimSpace(evidence.Summary) if message == "" { message = "upstream request failed" } typeValue := strings.TrimSpace(evidence.Type) if typeValue == "" { switch evidence.Hint { case execution.FailureHintInvalidCredential: typeValue = "authentication_error" case execution.FailureHintRateLimited: typeValue = "rate_limit_error" case execution.FailureHintModelUnavailable: typeValue = "model_not_found" default: typeValue = "api_error" } } codeValue := strings.TrimSpace(evidence.Code) var value any switch clientProtocol { case protocol.Anthropic: payload := struct { Type string `json:"type"` Error struct { Type string `json:"type"` Message string `json:"message"` } `json:"error"` }{Type: "error"} payload.Error.Type = typeValue payload.Error.Message = message value = payload case protocol.Gemini: if status < 100 || status > 599 { status = http.StatusBadGateway } if codeValue == "" { codeValue = strings.ToUpper(typeValue) } payload := struct { Error struct { Code int `json:"code"` Message string `json:"message"` Status string `json:"status"` } `json:"error"` }{} payload.Error.Code = status payload.Error.Message = message payload.Error.Status = codeValue value = payload default: payload := struct { Error struct { Message string `json:"message"` Type string `json:"type"` Code string `json:"code,omitempty"` } `json:"error"` }{} payload.Error.Message = message payload.Error.Type = typeValue payload.Error.Code = codeValue value = payload } body, err := json.Marshal(value) if err != nil { return []byte(`{"error":{"message":"upstream request failed","type":"api_error"}}`) } return body } func executionRepresentationFailure(result UpstreamResult, err error) UpstreamResult { evidence := execution.ErrorEvidence{ Kind: execution.ErrorKindInternal, OriginHint: execution.ErrorOriginInternal, ScopeHint: execution.ErrorScopeRequest, Code: "response_representation_invalid", Summary: "Upstream response representation could not be processed.", ReplaySafety: execution.ReplaySafetyUnknown, } if result.ResponseStarted { evidence.StatusCode = result.StatusCode } return UpstreamResult{ Err: err, StatusCode: result.StatusCode, RequestWritten: result.RequestWritten, DispatchState: result.DispatchState, ResponseStarted: result.ResponseStarted, UpstreamProtocol: result.UpstreamProtocol, AppliedReasoning: result.AppliedReasoning.Clone(), UpstreamRequestID: result.UpstreamRequestID, ExecutionError: &evidence, ErrorSummary: evidence.Summary, } } func newExecutionAttemptSpec(input ForwardInput) (execution.AttemptSpec, error) { if input.Request == nil { return execution.AttemptSpec{}, fmt.Errorf("request is required") } headers := cloneEndToEndHeaders(input.Request.Header) removeDownstreamCredentials(headers) for name, value := range input.Group.HeaderRules.Set { headers.Set(name, strings.ReplaceAll(value, "${API_KEY}", input.APIKey)) } for _, name := range input.Group.HeaderRules.Remove { headers.Del(name) } sanitizeUpstreamRequestHeaders(headers) headers.Set("Accept-Encoding", "identity") spec := execution.NewAttemptSpec(execution.AttemptSpec{ RequestID: input.RequestID, AttemptID: input.AttemptID, Sequence: input.AttemptSequence, ChannelID: input.ChannelID, RouteMode: input.RouteMode, ClientProtocol: input.ClientProtocol, Operation: input.Operation, RouteRequirement: input.RouteRequirement, ResponsesStorePreference: input.ResponsesStorePreference, ResponsesStoreDowngraded: input.ResponsesStoreDowngraded, ClientModel: input.ExternalModel, UpstreamModel: input.UpstreamModelID, Method: input.Request.Method, Path: input.Request.Path, RawQuery: input.Request.RawQuery, Header: headers, ConfiguredHeaders: input.Group.HeaderRules.ConfiguredNames(), Body: input.Request.Body, IncludeUsage: input.ObserveUsage, ForceCredentialRefresh: input.ForceCredentialRefresh, ContinuityKey: input.ContinuityKey, TargetConfig: input.TargetConfig, Timeouts: execution.AttemptTimeouts{ FirstByte: input.Group.Timeouts.FirstByte, Request: input.Group.Timeouts.Request, StreamIdle: input.Group.Timeouts.StreamIdle, }, Credential: input.Credential, Proxy: input.Proxy, ProxyFingerprint: input.ProxyFingerprint, }) if spec.ResponsesStoreDowngraded { body, err := forceStatelessResponsesRequest(spec.Body) if err != nil { return execution.AttemptSpec{}, err } spec.Body = body platformheader.StripRepresentationMetadata(spec.Header) } if err := spec.Validate(); err != nil { return execution.AttemptSpec{}, err } return spec, nil } func upstreamFromExecutionResult( ctx context.Context, input ForwardInput, result execution.AttemptResult, ) UpstreamResult { upstream := baseExecutionResult(input, result.DispatchState, result.ResponseStarted, result.StatusCode, result.Header, result.Model, result.UpstreamRequestID, result.Usage, result.Error) if result.AppliedReasoning != nil { upstream.AppliedReasoning = result.AppliedReasoning.Clone() } upstream.UpstreamProtocol = result.UpstreamProtocol if input.ClientProtocol == protocol.OpenAIImages || input.ClientProtocol == protocol.OpenAIEmbeddings { // AttemptResult owns Body after the executor returns. Buffered opaque // representations consume it synchronously, so move that ownership across // the internal boundary instead of cloning a large payload twice. upstream.Body = result.Body upstream.ClassificationBody = result.Body } else { upstream.Body = append([]byte(nil), result.Body...) upstream.ClassificationBody = append([]byte(nil), result.Body...) } if !result.ResponseStarted && result.Error != nil { upstream.Err = executionFailureError(ctx, result.Error) } return upstream } func upstreamFromExecutionStreamResult( ctx context.Context, input ForwardInput, result execution.StreamResult, streamUsage *execution.UsageEvidence, ) UpstreamResult { usageEvidence := result.Usage if usageEvidence == nil { usageEvidence = streamUsage } upstream := baseExecutionResult(input, result.DispatchState, result.ResponseStarted, result.StatusCode, result.Header, result.Model, result.UpstreamRequestID, usageEvidence, result.Error) if result.AppliedReasoning != nil { upstream.AppliedReasoning = result.AppliedReasoning.Clone() } upstream.UpstreamProtocol = result.UpstreamProtocol if !result.ResponseStarted && result.Error != nil { upstream.Err = executionFailureError(ctx, result.Error) } return upstream } func baseExecutionResult( input ForwardInput, dispatchState execution.DispatchState, responseStarted bool, statusCode int, header http.Header, model string, upstreamRequestID string, usageEvidence *execution.UsageEvidence, errorEvidence *execution.ErrorEvidence, ) UpstreamResult { result := UpstreamResult{ StatusCode: statusCode, Header: cloneEndToEndHeaders(header), UpstreamReportedModel: model, ResponseModelObserved: model != "", RequestWritten: dispatchState == execution.DispatchMaybeSent, DispatchState: dispatchState, ResponseStarted: responseStarted, UpstreamRequestID: upstreamRequestID, } if usageEvidence != nil { result.Usage = usageEvidence.Normalized } else if input.ObserveUsage { result.Usage = usage.Result{State: usage.StateMissing} } else { result.Usage = usage.Result{State: usage.StateNotApplicable} } if errorEvidence != nil { copy := errorEvidence.Clone() result.ExecutionError = © result.ErrorSummary = copy.Summary result.ProviderErrorBeforeCommit = responseStarted && statusCode >= http.StatusOK && statusCode < http.StatusMultipleChoices } return result } func executionFailureError(ctx context.Context, evidence *execution.ErrorEvidence) error { if ctx != nil && ctx.Err() != nil { return ctx.Err() } if evidence == nil { return fmt.Errorf("upstream execution failed") } switch evidence.Kind { case execution.ErrorKindCanceled: return context.Canceled case execution.ErrorKindTimeout: return upstreamExecutionTimeoutError{} case execution.ErrorKindInvalidRequest, execution.ErrorKindProvider, execution.ErrorKindInternal: return fmt.Errorf("%w: upstream execution failed", ErrUpstreamProtocol) default: return fmt.Errorf("upstream execution failed") } } type upstreamExecutionTimeoutError struct{} func (upstreamExecutionTimeoutError) Error() string { return "upstream execution timed out" } func (upstreamExecutionTimeoutError) Timeout() bool { return true } func (upstreamExecutionTimeoutError) Temporary() bool { return true } func executionInputFailure(cause error) UpstreamResult { if cause == nil { cause = fmt.Errorf("execution runtime is unavailable") } evidence := execution.ErrorEvidence{ Kind: execution.ErrorKindInvalidRequest, Summary: "invalid execution attempt", } return UpstreamResult{ Err: fmt.Errorf("%w: %v", ErrUpstreamProtocol, cause), DispatchState: execution.DispatchNotSent, ExecutionError: &evidence, ErrorSummary: evidence.Summary, } } func appendExecutionErrorBody(current, chunk []byte) []byte { remaining := maxStreamingErrorBodyBytes - len(current) if remaining <= 0 { return current } if len(chunk) > remaining { chunk = chunk[:remaining] } return append(current, chunk...) } func executionStreamProtocolFailure(cause error) error { if cause == nil { cause = fmt.Errorf("invalid upstream SSE stream") } return &streamFailure{ kind: streamFailureProtocol, err: fmt.Errorf("%w: %v", ErrUpstreamProtocol, cause), } } func preferCapturedStreamUsage( current usage.Result, captured usage.Result, ) usage.Result { switch captured.State { case usage.StateComplete: if current.State != usage.StateComplete { return captured } case usage.StatePartial: if current.State == usage.StateMissing || current.State == "" { return captured } case usage.StateMissing: if current.State == "" { return captured } } return current } func executionStreamObservation( ctx context.Context, terminal execution.StreamResult, downstreamErr error, streamEvents *streamEventObserver, ) StreamObservation { if downstreamErr != nil { return observeStreamTermination(ctx, downstreamErr, streamEvents) } if terminal.Error == nil { return streamEvents.endObservation() } switch terminal.Error.Kind { case execution.ErrorKindCanceled: return observeStreamTermination(ctx, context.Canceled, streamEvents) case execution.ErrorKindTimeout: return streamTerminalObservation(StreamEndIdleTimeout) case execution.ErrorKindProvider, execution.ErrorKindHTTP: observation := streamEvents.endObservation() if observation.EndReason == StreamEndSSEError { return observation } return StreamObservation{ EndReason: StreamEndSSEError, ErrorSummary: terminal.Error.Summary, } case execution.ErrorKindInvalidRequest, execution.ErrorKindInternal: return streamTerminalObservation(StreamEndUpstreamProtocolError) default: return streamTerminalObservation(StreamEndUpstreamTerminated) } } var _ AttemptForwarder = (*ExecutionForwarder)(nil)