mirror of
https://github.com/router-for-me/CLIProxyAPI.git
synced 2026-02-02 20:40:52 +08:00
feat(config): add payload filter rules to remove JSON paths
Introduce `Filter` rules in the payload configuration to remove specified JSON paths from the payload. Update related helper functions and add examples to `config.example.yaml`.
This commit is contained in:
@@ -285,24 +285,31 @@ oauth-model-alias:
|
|||||||
# default: # Default rules only set parameters when they are missing in the payload.
|
# default: # Default rules only set parameters when they are missing in the payload.
|
||||||
# - models:
|
# - models:
|
||||||
# - name: "gemini-2.5-pro" # Supports wildcards (e.g., "gemini-*")
|
# - name: "gemini-2.5-pro" # Supports wildcards (e.g., "gemini-*")
|
||||||
# protocol: "gemini" # restricts the rule to a specific protocol, options: openai, gemini, claude, codex
|
# protocol: "gemini" # restricts the rule to a specific protocol, options: openai, gemini, claude, codex, antigravity
|
||||||
# params: # JSON path (gjson/sjson syntax) -> value
|
# params: # JSON path (gjson/sjson syntax) -> value
|
||||||
# "generationConfig.thinkingConfig.thinkingBudget": 32768
|
# "generationConfig.thinkingConfig.thinkingBudget": 32768
|
||||||
# default-raw: # Default raw rules set parameters using raw JSON when missing (must be valid JSON).
|
# default-raw: # Default raw rules set parameters using raw JSON when missing (must be valid JSON).
|
||||||
# - models:
|
# - models:
|
||||||
# - name: "gemini-2.5-pro" # Supports wildcards (e.g., "gemini-*")
|
# - name: "gemini-2.5-pro" # Supports wildcards (e.g., "gemini-*")
|
||||||
# protocol: "gemini" # restricts the rule to a specific protocol, options: openai, gemini, claude, codex
|
# protocol: "gemini" # restricts the rule to a specific protocol, options: openai, gemini, claude, codex, antigravity
|
||||||
# params: # JSON path (gjson/sjson syntax) -> raw JSON value (strings are used as-is, must be valid JSON)
|
# params: # JSON path (gjson/sjson syntax) -> raw JSON value (strings are used as-is, must be valid JSON)
|
||||||
# "generationConfig.responseJsonSchema": "{\"type\":\"object\",\"properties\":{\"answer\":{\"type\":\"string\"}}}"
|
# "generationConfig.responseJsonSchema": "{\"type\":\"object\",\"properties\":{\"answer\":{\"type\":\"string\"}}}"
|
||||||
# override: # Override rules always set parameters, overwriting any existing values.
|
# override: # Override rules always set parameters, overwriting any existing values.
|
||||||
# - models:
|
# - models:
|
||||||
# - name: "gpt-*" # Supports wildcards (e.g., "gpt-*")
|
# - name: "gpt-*" # Supports wildcards (e.g., "gpt-*")
|
||||||
# protocol: "codex" # restricts the rule to a specific protocol, options: openai, gemini, claude, codex
|
# protocol: "codex" # restricts the rule to a specific protocol, options: openai, gemini, claude, codex, antigravity
|
||||||
# params: # JSON path (gjson/sjson syntax) -> value
|
# params: # JSON path (gjson/sjson syntax) -> value
|
||||||
# "reasoning.effort": "high"
|
# "reasoning.effort": "high"
|
||||||
# override-raw: # Override raw rules always set parameters using raw JSON (must be valid JSON).
|
# override-raw: # Override raw rules always set parameters using raw JSON (must be valid JSON).
|
||||||
# - models:
|
# - models:
|
||||||
# - name: "gpt-*" # Supports wildcards (e.g., "gpt-*")
|
# - name: "gpt-*" # Supports wildcards (e.g., "gpt-*")
|
||||||
# protocol: "codex" # restricts the rule to a specific protocol, options: openai, gemini, claude, codex
|
# protocol: "codex" # restricts the rule to a specific protocol, options: openai, gemini, claude, codex, antigravity
|
||||||
# params: # JSON path (gjson/sjson syntax) -> raw JSON value (strings are used as-is, must be valid JSON)
|
# params: # JSON path (gjson/sjson syntax) -> raw JSON value (strings are used as-is, must be valid JSON)
|
||||||
# "response_format": "{\"type\":\"json_schema\",\"json_schema\":{\"name\":\"answer\",\"schema\":{\"type\":\"object\"}}}"
|
# "response_format": "{\"type\":\"json_schema\",\"json_schema\":{\"name\":\"answer\",\"schema\":{\"type\":\"object\"}}}"
|
||||||
|
# filter: # Filter rules remove specified parameters from the payload.
|
||||||
|
# - models:
|
||||||
|
# - name: "gemini-2.5-pro" # Supports wildcards (e.g., "gemini-*")
|
||||||
|
# protocol: "gemini" # restricts the rule to a specific protocol, options: openai, gemini, claude, codex, antigravity
|
||||||
|
# params: # JSON paths (gjson/sjson syntax) to remove from the payload
|
||||||
|
# - "generationConfig.thinkingConfig.thinkingBudget"
|
||||||
|
# - "generationConfig.responseJsonSchema"
|
||||||
|
|||||||
@@ -229,6 +229,16 @@ type PayloadConfig struct {
|
|||||||
Override []PayloadRule `yaml:"override" json:"override"`
|
Override []PayloadRule `yaml:"override" json:"override"`
|
||||||
// OverrideRaw defines rules that always set raw JSON values, overwriting any existing values.
|
// OverrideRaw defines rules that always set raw JSON values, overwriting any existing values.
|
||||||
OverrideRaw []PayloadRule `yaml:"override-raw" json:"override-raw"`
|
OverrideRaw []PayloadRule `yaml:"override-raw" json:"override-raw"`
|
||||||
|
// Filter defines rules that remove parameters from the payload by JSON path.
|
||||||
|
Filter []PayloadFilterRule `yaml:"filter" json:"filter"`
|
||||||
|
}
|
||||||
|
|
||||||
|
// PayloadFilterRule describes a rule to remove specific JSON paths from matching model payloads.
|
||||||
|
type PayloadFilterRule struct {
|
||||||
|
// Models lists model entries with name pattern and protocol constraint.
|
||||||
|
Models []PayloadModelRule `yaml:"models" json:"models"`
|
||||||
|
// Params lists JSON paths (gjson/sjson syntax) to remove from the payload.
|
||||||
|
Params []string `yaml:"params" json:"params"`
|
||||||
}
|
}
|
||||||
|
|
||||||
// PayloadRule describes a single rule targeting a list of models with parameter updates.
|
// PayloadRule describes a single rule targeting a list of models with parameter updates.
|
||||||
|
|||||||
@@ -21,7 +21,7 @@ func applyPayloadConfigWithRoot(cfg *config.Config, model, protocol, root string
|
|||||||
return payload
|
return payload
|
||||||
}
|
}
|
||||||
rules := cfg.Payload
|
rules := cfg.Payload
|
||||||
if len(rules.Default) == 0 && len(rules.DefaultRaw) == 0 && len(rules.Override) == 0 && len(rules.OverrideRaw) == 0 {
|
if len(rules.Default) == 0 && len(rules.DefaultRaw) == 0 && len(rules.Override) == 0 && len(rules.OverrideRaw) == 0 && len(rules.Filter) == 0 {
|
||||||
return payload
|
return payload
|
||||||
}
|
}
|
||||||
model = strings.TrimSpace(model)
|
model = strings.TrimSpace(model)
|
||||||
@@ -39,7 +39,7 @@ func applyPayloadConfigWithRoot(cfg *config.Config, model, protocol, root string
|
|||||||
// Apply default rules: first write wins per field across all matching rules.
|
// Apply default rules: first write wins per field across all matching rules.
|
||||||
for i := range rules.Default {
|
for i := range rules.Default {
|
||||||
rule := &rules.Default[i]
|
rule := &rules.Default[i]
|
||||||
if !payloadRuleMatchesModels(rule, protocol, candidates) {
|
if !payloadModelRulesMatch(rule.Models, protocol, candidates) {
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
for path, value := range rule.Params {
|
for path, value := range rule.Params {
|
||||||
@@ -64,7 +64,7 @@ func applyPayloadConfigWithRoot(cfg *config.Config, model, protocol, root string
|
|||||||
// Apply default raw rules: first write wins per field across all matching rules.
|
// Apply default raw rules: first write wins per field across all matching rules.
|
||||||
for i := range rules.DefaultRaw {
|
for i := range rules.DefaultRaw {
|
||||||
rule := &rules.DefaultRaw[i]
|
rule := &rules.DefaultRaw[i]
|
||||||
if !payloadRuleMatchesModels(rule, protocol, candidates) {
|
if !payloadModelRulesMatch(rule.Models, protocol, candidates) {
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
for path, value := range rule.Params {
|
for path, value := range rule.Params {
|
||||||
@@ -93,7 +93,7 @@ func applyPayloadConfigWithRoot(cfg *config.Config, model, protocol, root string
|
|||||||
// Apply override rules: last write wins per field across all matching rules.
|
// Apply override rules: last write wins per field across all matching rules.
|
||||||
for i := range rules.Override {
|
for i := range rules.Override {
|
||||||
rule := &rules.Override[i]
|
rule := &rules.Override[i]
|
||||||
if !payloadRuleMatchesModels(rule, protocol, candidates) {
|
if !payloadModelRulesMatch(rule.Models, protocol, candidates) {
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
for path, value := range rule.Params {
|
for path, value := range rule.Params {
|
||||||
@@ -111,7 +111,7 @@ func applyPayloadConfigWithRoot(cfg *config.Config, model, protocol, root string
|
|||||||
// Apply override raw rules: last write wins per field across all matching rules.
|
// Apply override raw rules: last write wins per field across all matching rules.
|
||||||
for i := range rules.OverrideRaw {
|
for i := range rules.OverrideRaw {
|
||||||
rule := &rules.OverrideRaw[i]
|
rule := &rules.OverrideRaw[i]
|
||||||
if !payloadRuleMatchesModels(rule, protocol, candidates) {
|
if !payloadModelRulesMatch(rule.Models, protocol, candidates) {
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
for path, value := range rule.Params {
|
for path, value := range rule.Params {
|
||||||
@@ -130,29 +130,33 @@ func applyPayloadConfigWithRoot(cfg *config.Config, model, protocol, root string
|
|||||||
out = updated
|
out = updated
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
// Apply filter rules: remove matching paths from payload.
|
||||||
|
for i := range rules.Filter {
|
||||||
|
rule := &rules.Filter[i]
|
||||||
|
if !payloadModelRulesMatch(rule.Models, protocol, candidates) {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
for _, path := range rule.Params {
|
||||||
|
fullPath := buildPayloadPath(root, path)
|
||||||
|
if fullPath == "" {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
updated, errDel := sjson.DeleteBytes(out, fullPath)
|
||||||
|
if errDel != nil {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
out = updated
|
||||||
|
}
|
||||||
|
}
|
||||||
return out
|
return out
|
||||||
}
|
}
|
||||||
|
|
||||||
func payloadRuleMatchesModels(rule *config.PayloadRule, protocol string, models []string) bool {
|
func payloadModelRulesMatch(rules []config.PayloadModelRule, protocol string, models []string) bool {
|
||||||
if rule == nil || len(models) == 0 {
|
if len(rules) == 0 || len(models) == 0 {
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
for _, model := range models {
|
for _, model := range models {
|
||||||
if payloadRuleMatchesModel(rule, model, protocol) {
|
for _, entry := range rules {
|
||||||
return true
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
|
|
||||||
func payloadRuleMatchesModel(rule *config.PayloadRule, model, protocol string) bool {
|
|
||||||
if rule == nil {
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
if len(rule.Models) == 0 {
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
for _, entry := range rule.Models {
|
|
||||||
name := strings.TrimSpace(entry.Name)
|
name := strings.TrimSpace(entry.Name)
|
||||||
if name == "" {
|
if name == "" {
|
||||||
continue
|
continue
|
||||||
@@ -164,6 +168,7 @@ func payloadRuleMatchesModel(rule *config.PayloadRule, model, protocol string) b
|
|||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -19,6 +19,7 @@ type AmpCode = internalconfig.AmpCode
|
|||||||
type OAuthModelAlias = internalconfig.OAuthModelAlias
|
type OAuthModelAlias = internalconfig.OAuthModelAlias
|
||||||
type PayloadConfig = internalconfig.PayloadConfig
|
type PayloadConfig = internalconfig.PayloadConfig
|
||||||
type PayloadRule = internalconfig.PayloadRule
|
type PayloadRule = internalconfig.PayloadRule
|
||||||
|
type PayloadFilterRule = internalconfig.PayloadFilterRule
|
||||||
type PayloadModelRule = internalconfig.PayloadModelRule
|
type PayloadModelRule = internalconfig.PayloadModelRule
|
||||||
|
|
||||||
type GeminiKey = internalconfig.GeminiKey
|
type GeminiKey = internalconfig.GeminiKey
|
||||||
|
|||||||
Reference in New Issue
Block a user