feat: 算力引擎 Go 后端核心(new-api)
- 统一 OpenAI 兼容 /v1 中继 + 渠道/额度/令牌/流水 - 各领域包:relay 模型网关、model 数据层、controller 管理 API
This commit is contained in:
@@ -0,0 +1,158 @@
|
||||
package operation_setting
|
||||
|
||||
import "github.com/QuantumNous/new-api/setting/config"
|
||||
|
||||
type ChannelAffinityKeySource struct {
|
||||
Type string `json:"type"` // context_int, context_string, request_header, gjson
|
||||
Key string `json:"key,omitempty"`
|
||||
Path string `json:"path,omitempty"`
|
||||
}
|
||||
|
||||
type ChannelAffinityRule struct {
|
||||
Name string `json:"name"`
|
||||
ModelRegex []string `json:"model_regex"`
|
||||
PathRegex []string `json:"path_regex"`
|
||||
UserAgentInclude []string `json:"user_agent_include,omitempty"`
|
||||
KeySources []ChannelAffinityKeySource `json:"key_sources"`
|
||||
|
||||
ValueRegex string `json:"value_regex"`
|
||||
TTLSeconds int `json:"ttl_seconds"`
|
||||
|
||||
ParamOverrideTemplate map[string]interface{} `json:"param_override_template,omitempty"`
|
||||
|
||||
SkipRetryOnFailure bool `json:"skip_retry_on_failure"`
|
||||
|
||||
IncludeUsingGroup bool `json:"include_using_group"`
|
||||
IncludeModelName bool `json:"include_model_name"`
|
||||
IncludeRuleName bool `json:"include_rule_name"`
|
||||
}
|
||||
|
||||
type ChannelAffinitySetting struct {
|
||||
Enabled bool `json:"enabled"`
|
||||
SwitchOnSuccess bool `json:"switch_on_success"`
|
||||
KeepOnChannelDisabled bool `json:"keep_on_channel_disabled"`
|
||||
MaxEntries int `json:"max_entries"`
|
||||
DefaultTTLSeconds int `json:"default_ttl_seconds"`
|
||||
Rules []ChannelAffinityRule `json:"rules"`
|
||||
}
|
||||
|
||||
// Keep Codex CLI passthrough aligned with upstream. Codex uses lower-case
|
||||
// header names, while HTTP matching here is case-insensitive.
|
||||
// Request session/thread headers:
|
||||
// https://github.com/openai/codex/commit/7c7b4861d88960f7e3bd5b7f30f8351be666dd84
|
||||
// Responses metadata headers/client_metadata:
|
||||
// https://github.com/openai/codex/commit/14df0e8833aad0d6d78287954b61ffac67af936c
|
||||
// x-codex-turn-state response/request round trip:
|
||||
// https://github.com/openai/codex/commit/ebdd8795e924a8149b616e46ca2ed7848c207a4b
|
||||
var codexCliPassThroughHeaders = []string{
|
||||
"Originator",
|
||||
"Session_id",
|
||||
"Thread_id",
|
||||
"Session-Id",
|
||||
"Thread-Id",
|
||||
"X-Client-Request-Id",
|
||||
"User-Agent",
|
||||
"X-Codex-Beta-Features",
|
||||
"X-Codex-Turn-State",
|
||||
"X-Codex-Turn-Metadata",
|
||||
"X-Codex-Window-Id",
|
||||
"X-Codex-Parent-Thread-Id",
|
||||
//"X-Codex-Installation-Id",
|
||||
"X-OpenAI-Subagent",
|
||||
"X-OpenAI-Memgen-Request",
|
||||
//"X-OAI-Attestation",
|
||||
"X-ResponsesAPI-Include-Timing-Metrics",
|
||||
"X-OpenAI-Internal-Codex-Responses-Lite",
|
||||
}
|
||||
|
||||
var claudeCliPassThroughHeaders = []string{
|
||||
"X-Stainless-Arch",
|
||||
"X-Stainless-Lang",
|
||||
"X-Stainless-Os",
|
||||
"X-Stainless-Package-Version",
|
||||
"X-Stainless-Retry-Count",
|
||||
"X-Stainless-Runtime",
|
||||
"X-Stainless-Runtime-Version",
|
||||
"X-Stainless-Timeout",
|
||||
"User-Agent",
|
||||
"X-App",
|
||||
"Anthropic-Beta",
|
||||
"Anthropic-Dangerous-Direct-Browser-Access",
|
||||
"Anthropic-Version",
|
||||
}
|
||||
|
||||
func buildPassHeaderTemplate(headers []string) map[string]interface{} {
|
||||
clonedHeaders := make([]string, 0, len(headers))
|
||||
clonedHeaders = append(clonedHeaders, headers...)
|
||||
return map[string]interface{}{
|
||||
"operations": []map[string]interface{}{
|
||||
{
|
||||
"mode": "pass_headers",
|
||||
"value": clonedHeaders,
|
||||
"keep_origin": true,
|
||||
},
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
func buildCodexPassHeaderTemplate() map[string]interface{} {
|
||||
requestHeaders := make([]string, 0, len(codexCliPassThroughHeaders))
|
||||
requestHeaders = append(requestHeaders, codexCliPassThroughHeaders...)
|
||||
return map[string]interface{}{
|
||||
"operations": []map[string]interface{}{
|
||||
{
|
||||
"mode": "pass_headers",
|
||||
"value": requestHeaders,
|
||||
"keep_origin": true,
|
||||
},
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
var channelAffinitySetting = ChannelAffinitySetting{
|
||||
Enabled: true,
|
||||
SwitchOnSuccess: true,
|
||||
KeepOnChannelDisabled: false,
|
||||
MaxEntries: 100_000,
|
||||
DefaultTTLSeconds: 3600,
|
||||
Rules: []ChannelAffinityRule{
|
||||
{
|
||||
Name: "codex cli trace",
|
||||
ModelRegex: []string{"^gpt-.*$"},
|
||||
PathRegex: []string{"/v1/responses"},
|
||||
KeySources: []ChannelAffinityKeySource{
|
||||
{Type: "gjson", Path: "prompt_cache_key"},
|
||||
},
|
||||
ValueRegex: "",
|
||||
TTLSeconds: 0,
|
||||
ParamOverrideTemplate: buildCodexPassHeaderTemplate(),
|
||||
SkipRetryOnFailure: true,
|
||||
IncludeUsingGroup: true,
|
||||
IncludeRuleName: true,
|
||||
UserAgentInclude: nil,
|
||||
},
|
||||
{
|
||||
Name: "claude cli trace",
|
||||
ModelRegex: []string{"^claude-.*$"},
|
||||
PathRegex: []string{"/v1/messages"},
|
||||
KeySources: []ChannelAffinityKeySource{
|
||||
{Type: "gjson", Path: "metadata.user_id"},
|
||||
},
|
||||
ValueRegex: "",
|
||||
TTLSeconds: 0,
|
||||
ParamOverrideTemplate: buildPassHeaderTemplate(claudeCliPassThroughHeaders),
|
||||
SkipRetryOnFailure: true,
|
||||
IncludeUsingGroup: true,
|
||||
IncludeRuleName: true,
|
||||
UserAgentInclude: nil,
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
func init() {
|
||||
config.GlobalConfig.Register("channel_affinity_setting", &channelAffinitySetting)
|
||||
}
|
||||
|
||||
func GetChannelAffinitySetting() *ChannelAffinitySetting {
|
||||
return &channelAffinitySetting
|
||||
}
|
||||
Reference in New Issue
Block a user