Files
sub2api-cn-relay-manager/internal/access/openai_responses_repair.go

87 lines
2.5 KiB
Go

package access
import (
"context"
"strings"
"sub2api-cn-relay-manager/internal/host/sub2api"
)
func SuspectsOpenAIResponsesCapabilityMismatch(probe sub2api.ProbeResult) bool {
if probe.OK {
return false
}
message := strings.ToLower(strings.TrimSpace(probe.Message))
if message == "" {
return false
}
if strings.Contains(message, "api returned 403: forbidden") {
return true
}
return strings.Contains(message, "responses api") &&
(strings.Contains(message, "当前测试接口仅支持") ||
strings.Contains(message, "账号本身可正常使用") ||
strings.Contains(message, "please directly") ||
strings.Contains(message, "actual api"))
}
func ShouldAttemptOpenAIResponsesCapabilityRepair(suspect bool, completion sub2api.GatewayCompletionResult) bool {
if !suspect || completion.OK {
return false
}
if completion.StatusCode != 502 && completion.StatusCode != 503 {
return false
}
body := strings.ToLower(strings.TrimSpace(completion.BodyPreview))
return strings.Contains(body, "service temporarily unavailable") ||
strings.Contains(body, "no available accounts")
}
func (s *Service) maybeRepairOpenAIResponsesCapability(ctx context.Context, req ClosureRequest, completionReq sub2api.GatewayCompletionCheckRequest, completion sub2api.GatewayCompletionResult) (sub2api.GatewayCompletionResult, error) {
if !ShouldAttemptOpenAIResponsesCapabilityRepair(req.ResponsesCapabilitySuspect, completion) {
return completion, nil
}
accountIDs := normalizedAccountIDs(req.AccountIDs)
if len(accountIDs) == 0 {
return completion, nil
}
if err := RepairOpenAIResponsesCapability(ctx, s.host, accountIDs); err != nil {
return completion, nil
}
return s.checkGatewayCompletionWithRetry(ctx, completionReq)
}
func RepairOpenAIResponsesCapability(ctx context.Context, host Host, accountIDs []string) error {
if host == nil {
return nil
}
normalized := normalizedAccountIDs(accountIDs)
if len(normalized) == 0 {
return nil
}
if err := host.DisableOpenAIResponsesAPI(ctx, normalized); err != nil {
return err
}
if err := host.ClearTempUnschedulable(ctx, normalized); err != nil {
return nil
}
return nil
}
func normalizedAccountIDs(accountIDs []string) []string {
seen := map[string]struct{}{}
values := make([]string, 0, len(accountIDs))
for _, rawID := range accountIDs {
accountID := strings.TrimSpace(rawID)
if accountID == "" {
continue
}
if _, ok := seen[accountID]; ok {
continue
}
seen[accountID] = struct{}{}
values = append(values, accountID)
}
return values
}