@@ -3,6 +3,7 @@ package plugin
33import (
44 "log/slog"
55 "net/http"
6+ "strings"
67 "time"
78
89 "github.com/gin-gonic/gin"
@@ -78,14 +79,9 @@ func (f *Forwarder) Forward(c *gin.Context) {
7879 }
7980 defer releaseClientQuota ()
8081
81- routes , err := routing . ListEligibleGroups ( c . Request . Context (), f . db , state . keyInfo . UserID , state . requestedPlatform , state . keyInfo . UserGroupRates , routing.Requirements {
82+ routes := routesForAPIKey ( state , routing.Requirements {
8283 NeedsImage : requestNeedsImage (state .requestPath , state .model ),
8384 })
84- if err != nil {
85- slog .Error ("查询候选分组失败" , "platform" , state .requestedPlatform , "model" , state .model , "error" , err )
86- openAIError (c , http .StatusServiceUnavailable , "server_error" , "routing_unavailable" , "请求暂时无法完成,请稍后重试" )
87- return
88- }
8985 if len (routes ) == 0 {
9086 slog .Warn ("没有可用候选分组" , "platform" , state .requestedPlatform , "model" , state .model , "user_id" , state .keyInfo .UserID )
9187 openAIError (c , http .StatusServiceUnavailable , "server_error" , "no_available_route" , "请求暂时无法完成,请稍后重试" )
@@ -198,6 +194,69 @@ func (f *Forwarder) Forward(c *gin.Context) {
198194 openAIError (c , 503 , "server_error" , "all_routes_failed" , "请求暂时无法完成,请稍后重试" )
199195}
200196
197+ func routesForAPIKey (state * forwardState , requirements routing.Requirements ) []routing.Candidate {
198+ if state == nil || state .keyInfo == nil {
199+ return nil
200+ }
201+ if ! apiKeyGroupMatchesRequirements (state .keyInfo , requirements ) {
202+ return nil
203+ }
204+ return []routing.Candidate {keyInfoRoute (state .keyInfo )}
205+ }
206+
207+ func apiKeyGroupMatchesRequirements (keyInfo * auth.APIKeyInfo , requirements routing.Requirements ) bool {
208+ if keyInfo == nil {
209+ return false
210+ }
211+ if requirements .NeedsImage && strings .EqualFold (keyInfo .GroupPlatform , "openai" ) {
212+ return pluginSettingEnabledForKey (keyInfo .GroupPluginSettings , "openai" , "image_enabled" )
213+ }
214+ return true
215+ }
216+
217+ func pluginSettingEnabledForKey (settings map [string ]map [string ]string , plugin , key string ) bool {
218+ for pluginName , kv := range settings {
219+ if ! strings .EqualFold (pluginName , plugin ) {
220+ continue
221+ }
222+ for k , v := range kv {
223+ if strings .EqualFold (k , key ) {
224+ return strings .EqualFold (strings .TrimSpace (v ), "true" )
225+ }
226+ }
227+ }
228+ return false
229+ }
230+
231+ func keyInfoRoute (keyInfo * auth.APIKeyInfo ) routing.Candidate {
232+ return routing.Candidate {
233+ GroupID : keyInfo .GroupID ,
234+ Platform : keyInfo .GroupPlatform ,
235+ EffectiveRate : billing .ResolveBillingRateForGroup (keyInfo .UserGroupRates , keyInfo .GroupID , keyInfo .GroupRateMultiplier ),
236+ GroupRateMultiplier : keyInfo .GroupRateMultiplier ,
237+ GroupServiceTier : keyInfo .GroupServiceTier ,
238+ GroupForceInstructions : keyInfo .GroupForceInstructions ,
239+ GroupPluginSettings : clonePluginSettingsForKey (keyInfo .GroupPluginSettings ),
240+ }
241+ }
242+
243+ func clonePluginSettingsForKey (in map [string ]map [string ]string ) map [string ]map [string ]string {
244+ if len (in ) == 0 {
245+ return nil
246+ }
247+ out := make (map [string ]map [string ]string , len (in ))
248+ for plugin , settings := range in {
249+ if len (settings ) == 0 {
250+ continue
251+ }
252+ out [plugin ] = make (map [string ]string , len (settings ))
253+ for k , v := range settings {
254+ out [plugin ][k ] = v
255+ }
256+ }
257+ return out
258+ }
259+
201260func keyInfoForRoute (base * auth.APIKeyInfo , route routing.Candidate ) * auth.APIKeyInfo {
202261 info := * base
203262 info .GroupID = route .GroupID
0 commit comments