@@ -5,15 +5,18 @@ import (
55 "strings"
66
77 "github.com/router-for-me/CLIProxyAPI/v6/internal/config"
8+ "github.com/router-for-me/CLIProxyAPI/v6/internal/thinking"
9+ cliproxyexecutor "github.com/router-for-me/CLIProxyAPI/v6/sdk/cliproxy/executor"
810 "github.com/tidwall/gjson"
911 "github.com/tidwall/sjson"
1012)
1113
1214// applyPayloadConfigWithRoot behaves like applyPayloadConfig but treats all parameter
1315// paths as relative to the provided root path (for example, "request" for Gemini CLI)
1416// and restricts matches to the given protocol when supplied. Defaults are checked
15- // against the original payload when provided.
16- func applyPayloadConfigWithRoot (cfg * config.Config , model , protocol , root string , payload , original []byte ) []byte {
17+ // against the original payload when provided. requestedModel carries the client-visible
18+ // model name before alias resolution so payload rules can target aliases precisely.
19+ func applyPayloadConfigWithRoot (cfg * config.Config , model , protocol , root string , payload , original []byte , requestedModel string ) []byte {
1720 if cfg == nil || len (payload ) == 0 {
1821 return payload
1922 }
@@ -22,10 +25,11 @@ func applyPayloadConfigWithRoot(cfg *config.Config, model, protocol, root string
2225 return payload
2326 }
2427 model = strings .TrimSpace (model )
25- if model == "" {
28+ requestedModel = strings .TrimSpace (requestedModel )
29+ if model == "" && requestedModel == "" {
2630 return payload
2731 }
28- candidates := payloadModelCandidates (cfg , model , protocol )
32+ candidates := payloadModelCandidates (model , requestedModel )
2933 out := payload
3034 source := original
3135 if len (source ) == 0 {
@@ -163,63 +167,40 @@ func payloadRuleMatchesModel(rule *config.PayloadRule, model, protocol string) b
163167 return false
164168}
165169
166- func payloadModelCandidates (cfg * config. Config , model , protocol string ) []string {
170+ func payloadModelCandidates (model , requestedModel string ) []string {
167171 model = strings .TrimSpace (model )
168- if model == "" {
172+ requestedModel = strings .TrimSpace (requestedModel )
173+ if model == "" && requestedModel == "" {
169174 return nil
170175 }
171- candidates := []string {model }
172- if cfg == nil {
173- return candidates
174- }
175- aliases := payloadModelAliases (cfg , model , protocol )
176- if len (aliases ) == 0 {
177- return candidates
178- }
179- seen := map [string ]struct {}{strings .ToLower (model ): struct {}{}}
180- for _ , alias := range aliases {
181- alias = strings .TrimSpace (alias )
182- if alias == "" {
183- continue
176+ candidates := make ([]string , 0 , 3 )
177+ seen := make (map [string ]struct {}, 3 )
178+ addCandidate := func (value string ) {
179+ value = strings .TrimSpace (value )
180+ if value == "" {
181+ return
184182 }
185- key := strings .ToLower (alias )
183+ key := strings .ToLower (value )
186184 if _ , ok := seen [key ]; ok {
187- continue
185+ return
188186 }
189187 seen [key ] = struct {}{}
190- candidates = append (candidates , alias )
188+ candidates = append (candidates , value )
191189 }
192- return candidates
193- }
194-
195- func payloadModelAliases (cfg * config.Config , model , protocol string ) []string {
196- if cfg == nil {
197- return nil
198- }
199- model = strings .TrimSpace (model )
200- if model == "" {
201- return nil
202- }
203- channel := strings .ToLower (strings .TrimSpace (protocol ))
204- if channel == "" {
205- return nil
206- }
207- entries := cfg .OAuthModelAlias [channel ]
208- if len (entries ) == 0 {
209- return nil
190+ if model != "" {
191+ addCandidate (model )
210192 }
211- aliases := make ([]string , 0 , 2 )
212- for _ , entry := range entries {
213- if ! strings .EqualFold (strings .TrimSpace (entry .Name ), model ) {
214- continue
193+ if requestedModel != "" {
194+ parsed := thinking .ParseSuffix (requestedModel )
195+ base := strings .TrimSpace (parsed .ModelName )
196+ if base != "" {
197+ addCandidate (base )
215198 }
216- alias := strings .TrimSpace (entry .Alias )
217- if alias == "" {
218- continue
199+ if parsed .HasSuffix {
200+ addCandidate (requestedModel )
219201 }
220- aliases = append (aliases , alias )
221202 }
222- return aliases
203+ return candidates
223204}
224205
225206// buildPayloadPath combines an optional root path with a relative parameter path.
@@ -258,6 +239,35 @@ func payloadRawValue(value any) ([]byte, bool) {
258239 }
259240}
260241
242+ func payloadRequestedModel (opts cliproxyexecutor.Options , fallback string ) string {
243+ fallback = strings .TrimSpace (fallback )
244+ if len (opts .Metadata ) == 0 {
245+ return fallback
246+ }
247+ raw , ok := opts .Metadata [cliproxyexecutor .RequestedModelMetadataKey ]
248+ if ! ok || raw == nil {
249+ return fallback
250+ }
251+ switch v := raw .(type ) {
252+ case string :
253+ if strings .TrimSpace (v ) == "" {
254+ return fallback
255+ }
256+ return strings .TrimSpace (v )
257+ case []byte :
258+ if len (v ) == 0 {
259+ return fallback
260+ }
261+ trimmed := strings .TrimSpace (string (v ))
262+ if trimmed == "" {
263+ return fallback
264+ }
265+ return trimmed
266+ default :
267+ return fallback
268+ }
269+ }
270+
261271// matchModelPattern performs simple wildcard matching where '*' matches zero or more characters.
262272// Examples:
263273//
0 commit comments