channel_affinity_setting.go 3.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120
  1. package operation_setting
  2. import "github.com/QuantumNous/new-api/setting/config"
  3. type ChannelAffinityKeySource struct {
  4. Type string `json:"type"` // context_int, context_string, gjson
  5. Key string `json:"key,omitempty"`
  6. Path string `json:"path,omitempty"`
  7. }
  8. type ChannelAffinityRule struct {
  9. Name string `json:"name"`
  10. ModelRegex []string `json:"model_regex"`
  11. PathRegex []string `json:"path_regex"`
  12. UserAgentInclude []string `json:"user_agent_include,omitempty"`
  13. KeySources []ChannelAffinityKeySource `json:"key_sources"`
  14. ValueRegex string `json:"value_regex"`
  15. TTLSeconds int `json:"ttl_seconds"`
  16. ParamOverrideTemplate map[string]interface{} `json:"param_override_template,omitempty"`
  17. SkipRetryOnFailure bool `json:"skip_retry_on_failure,omitempty"`
  18. IncludeUsingGroup bool `json:"include_using_group"`
  19. IncludeRuleName bool `json:"include_rule_name"`
  20. }
  21. type ChannelAffinitySetting struct {
  22. Enabled bool `json:"enabled"`
  23. SwitchOnSuccess bool `json:"switch_on_success"`
  24. MaxEntries int `json:"max_entries"`
  25. DefaultTTLSeconds int `json:"default_ttl_seconds"`
  26. Rules []ChannelAffinityRule `json:"rules"`
  27. }
  28. var codexCliPassThroughHeaders = []string{
  29. "Originator",
  30. "Session_id",
  31. "User-Agent",
  32. "X-Codex-Beta-Features",
  33. "X-Codex-Turn-Metadata",
  34. }
  35. var claudeCliPassThroughHeaders = []string{
  36. "X-Stainless-Arch",
  37. "X-Stainless-Lang",
  38. "X-Stainless-Os",
  39. "X-Stainless-Package-Version",
  40. "X-Stainless-Retry-Count",
  41. "X-Stainless-Runtime",
  42. "X-Stainless-Runtime-Version",
  43. "X-Stainless-Timeout",
  44. "User-Agent",
  45. "X-App",
  46. "Anthropic-Beta",
  47. "Anthropic-Dangerous-Direct-Browser-Access",
  48. "Anthropic-Version",
  49. }
  50. func buildPassHeaderTemplate(headers []string) map[string]interface{} {
  51. clonedHeaders := make([]string, 0, len(headers))
  52. clonedHeaders = append(clonedHeaders, headers...)
  53. return map[string]interface{}{
  54. "operations": []map[string]interface{}{
  55. {
  56. "mode": "pass_headers",
  57. "value": clonedHeaders,
  58. "keep_origin": true,
  59. },
  60. },
  61. }
  62. }
  63. var channelAffinitySetting = ChannelAffinitySetting{
  64. Enabled: true,
  65. SwitchOnSuccess: true,
  66. MaxEntries: 100_000,
  67. DefaultTTLSeconds: 3600,
  68. Rules: []ChannelAffinityRule{
  69. {
  70. Name: "codex cli trace",
  71. ModelRegex: []string{"^gpt-.*$"},
  72. PathRegex: []string{"/v1/responses"},
  73. KeySources: []ChannelAffinityKeySource{
  74. {Type: "gjson", Path: "prompt_cache_key"},
  75. },
  76. ValueRegex: "",
  77. TTLSeconds: 0,
  78. ParamOverrideTemplate: buildPassHeaderTemplate(codexCliPassThroughHeaders),
  79. SkipRetryOnFailure: false,
  80. IncludeUsingGroup: true,
  81. IncludeRuleName: true,
  82. UserAgentInclude: nil,
  83. },
  84. {
  85. Name: "claude cli trace",
  86. ModelRegex: []string{"^claude-.*$"},
  87. PathRegex: []string{"/v1/messages"},
  88. KeySources: []ChannelAffinityKeySource{
  89. {Type: "gjson", Path: "metadata.user_id"},
  90. },
  91. ValueRegex: "",
  92. TTLSeconds: 0,
  93. ParamOverrideTemplate: buildPassHeaderTemplate(claudeCliPassThroughHeaders),
  94. SkipRetryOnFailure: false,
  95. IncludeUsingGroup: true,
  96. IncludeRuleName: true,
  97. UserAgentInclude: nil,
  98. },
  99. },
  100. }
  101. func init() {
  102. config.GlobalConfig.Register("channel_affinity_setting", &channelAffinitySetting)
  103. }
  104. func GetChannelAffinitySetting() *ChannelAffinitySetting {
  105. return &channelAffinitySetting
  106. }