From db66d78b6c56849f9fef6e21641dd583ab02afe1 Mon Sep 17 00:00:00 2001 From: feitianbubu Date: Wed, 15 Jul 2026 20:38:09 +0800 Subject: [PATCH 1/2] feat: support tencent tokenhub api key via openai-compatible protocol --- relay/channel/tencent/dispatch.go | 31 +++++++++++++++++++ relay/common/relay_info.go | 1 + relay/relay_adaptor.go | 2 +- .../src/features/channels/constants.ts | 2 +- 4 files changed, 34 insertions(+), 2 deletions(-) create mode 100644 relay/channel/tencent/dispatch.go diff --git a/relay/channel/tencent/dispatch.go b/relay/channel/tencent/dispatch.go new file mode 100644 index 00000000000..14c362f3f9c --- /dev/null +++ b/relay/channel/tencent/dispatch.go @@ -0,0 +1,31 @@ +package tencent + +import ( + "strings" + + "github.com/QuantumNous/new-api/relay/channel" + "github.com/QuantumNous/new-api/relay/channel/openai" + relaycommon "github.com/QuantumNous/new-api/relay/common" +) + +// DispatchAdaptor 按密钥格式分流:三段式 ak/sk 走原生 TC3,单段 TokenHub key 走 OpenAI 兼容。 +type DispatchAdaptor struct { + channel.Adaptor +} + +func (a *DispatchAdaptor) Init(info *relaycommon.RelayInfo) { + if strings.Contains(info.ApiKey, "|") { + a.Adaptor = &Adaptor{} + } else { + a.Adaptor = &openai.Adaptor{} + } + a.Adaptor.Init(info) +} + +func (a *DispatchAdaptor) GetModelList() []string { + return ModelList +} + +func (a *DispatchAdaptor) GetChannelName() string { + return ChannelName +} diff --git a/relay/common/relay_info.go b/relay/common/relay_info.go index 9f460ce5c6a..128e52e0c8c 100644 --- a/relay/common/relay_info.go +++ b/relay/common/relay_info.go @@ -342,6 +342,7 @@ var streamSupportedChannels = map[int]bool{ constant.ChannelTypeMiniMax: true, constant.ChannelTypeSiliconFlow: true, constant.ChannelTypeAdvancedCustom: true, + constant.ChannelTypeTencent: true, } func GenRelayInfoWs(c *gin.Context, ws *websocket.Conn) *RelayInfo { diff --git a/relay/relay_adaptor.go b/relay/relay_adaptor.go index 2922744654e..8920ba8c350 100644 --- a/relay/relay_adaptor.go +++ b/relay/relay_adaptor.go @@ -66,7 +66,7 @@ func GetAdaptor(apiType int) channel.Adaptor { case constant.APITypePaLM: return &palm.Adaptor{} case constant.APITypeTencent: - return &tencent.Adaptor{} + return &tencent.DispatchAdaptor{} case constant.APITypeXunfei: return &xunfei.Adaptor{} case constant.APITypeZhipu: diff --git a/web/default/src/features/channels/constants.ts b/web/default/src/features/channels/constants.ts index 877308b22f2..ff0fb274283 100644 --- a/web/default/src/features/channels/constants.ts +++ b/web/default/src/features/channels/constants.ts @@ -384,7 +384,7 @@ export const TYPE_TO_KEY_PROMPT: Record = { 15: 'Format: APIKey|SecretKey', 18: 'Format: APPID|APISecret|APIKey', 22: 'Format: APIKey-AppId, e.g., fastgpt-0sp2gtvfdgyi4k30jwlgwf1i-64f335d84283f05518e9e041', - 23: 'Format: AppId|SecretId|SecretKey', + 23: 'Format: TokenHub API Key, or legacy AppId|SecretId|SecretKey', 33: 'Format: Ak|Sk|Region', 50: 'Format: AccessKey|SecretKey (or just ApiKey if upstream is New API)', 51: 'Format: Access Key ID|Secret Access Key', From e31cfd54280bc536b9692e0b8a9b9ebd3f03c68b Mon Sep 17 00:00:00 2001 From: feitianbubu Date: Wed, 15 Jul 2026 20:57:03 +0800 Subject: [PATCH 2/2] fix: use tokenhub base url for tencent api key channels --- relay/channel/tencent/dispatch.go | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/relay/channel/tencent/dispatch.go b/relay/channel/tencent/dispatch.go index 14c362f3f9c..76ade5ca38f 100644 --- a/relay/channel/tencent/dispatch.go +++ b/relay/channel/tencent/dispatch.go @@ -3,11 +3,14 @@ package tencent import ( "strings" + "github.com/QuantumNous/new-api/constant" "github.com/QuantumNous/new-api/relay/channel" "github.com/QuantumNous/new-api/relay/channel/openai" relaycommon "github.com/QuantumNous/new-api/relay/common" ) +const tokenHubBaseURL = "https://tokenhub.tencentmaas.com" + // DispatchAdaptor 按密钥格式分流:三段式 ak/sk 走原生 TC3,单段 TokenHub key 走 OpenAI 兼容。 type DispatchAdaptor struct { channel.Adaptor @@ -18,6 +21,9 @@ func (a *DispatchAdaptor) Init(info *relaycommon.RelayInfo) { a.Adaptor = &Adaptor{} } else { a.Adaptor = &openai.Adaptor{} + if info.ChannelBaseUrl == "" || info.ChannelBaseUrl == constant.ChannelBaseURLs[constant.ChannelTypeTencent] { + info.ChannelBaseUrl = tokenHubBaseURL + } } a.Adaptor.Init(info) }