channel_affinity_setting.go 3.5 KB

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