fix(billing): allow upstream billing probe for TypeSafe API-key accounts

The create form shows the upstream billing auto-probe toggle for every
API-key platform and enables it by default. TypeSafe was added as an
API-key platform but not to IsUpstreamBillingProbeIdentity, so creating a
TypeSafe account with the default form state fails with
400 UPSTREAM_BILLING_PROBE_ACCOUNT_INVALID ("account is not an API key
account").

TypeSafe accounts store credentials.api_key/base_url like every other
API-key platform, which is all the probe reads. Add TypeSafe to the probe
identity set, and add typesafe.ai to the official API domains so accounts
on the default https://api.typesafe.ai base URL record "unsupported"
without sending the key to a path that cannot exist, matching the other
official providers.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
Kingsley
2026-10-02 10:45:53 +00:00
co-authored by Claude Opus 5.5
parent 458b92abd4
commit 66a9e2e6bb
2 changed files with 24 additions and 1 deletions
@@ -1013,7 +1013,8 @@ func IsUpstreamBillingProbeIdentity(platform, accountType string) bool {
}
switch platform {
case PlatformOpenAI, PlatformAnthropic, PlatformGemini, PlatformAntigravity, PlatformGrok,
PlatformKimi, PlatformZhipu, PlatformDeepseek, PlatformMiniMax, PlatformOpenCodeGo:
PlatformKimi, PlatformZhipu, PlatformDeepseek, PlatformMiniMax, PlatformOpenCodeGo,
PlatformTypeSafe:
return true
default:
return false
@@ -1052,6 +1053,7 @@ var upstreamBillingProbeOfficialAPIDomains = []string{
"bigmodel.cn",
"deepseek.com",
"opencode.ai",
"typesafe.ai",
}
func upstreamBillingProbeTargetIsOfficialAPI(baseURL string) bool {
@@ -17,6 +17,7 @@ func TestUpstreamBillingProbeIdentityCoversAllAPIKeyPlatforms(t *testing.T) {
for _, platform := range []string{
PlatformOpenAI, PlatformGrok, PlatformAnthropic, PlatformGemini, PlatformAntigravity,
PlatformKimi, PlatformZhipu, PlatformDeepseek, PlatformMiniMax, PlatformOpenCodeGo,
PlatformTypeSafe,
} {
require.True(t, IsUpstreamBillingProbeIdentity(platform, AccountTypeAPIKey), platform)
require.True(t, isUpstreamBillingProbeAccount(&Account{Platform: platform, Type: AccountTypeAPIKey}), platform)
@@ -174,6 +175,9 @@ func TestUpstreamBillingProbeOfficialAPIBaseURLIsUnsupportedWithoutRequest(t *te
{PlatformDeepseek, "https://api.deepseek.com/anthropic"},
{PlatformOpenCodeGo, "https://opencode.ai/zen/go/v1"},
{PlatformOpenCodeGo, "https://opencode.ai/zen/go"},
// TypeSafe 官方 System One API 同样不提供 /v1/sub2api/billing。
{PlatformTypeSafe, "https://api.typesafe.ai"},
{PlatformTypeSafe, "https://api.typesafe.ai/v1"},
}
for i, tc := range cases {
account := &Account{
@@ -217,6 +221,7 @@ func TestUpstreamBillingProbeOfficialAPIHostMatchingIsNormalized(t *testing.T) {
require.True(t, upstreamBillingProbeTargetIsOfficialAPI("https://api.deepseek.com/anthropic"))
require.True(t, upstreamBillingProbeTargetIsOfficialAPI("https://opencode.ai/zen/go/v1"))
require.True(t, upstreamBillingProbeTargetIsOfficialAPI("https://opencode.ai/zen/go"))
require.True(t, upstreamBillingProbeTargetIsOfficialAPI("https://api.typesafe.ai"))
// 相似但不同的注册域不拦:中转完全可能叫 *-x.ai 之外的任何名字。
require.False(t, upstreamBillingProbeTargetIsOfficialAPI("https://relay.example/v1"))
require.False(t, upstreamBillingProbeTargetIsOfficialAPI("https://notx.ai"))
@@ -228,6 +233,7 @@ func TestUpstreamBillingProbeOfficialAPIHostMatchingIsNormalized(t *testing.T) {
require.False(t, upstreamBillingProbeTargetIsOfficialAPI("https://notmoonshot.cn/v1"))
require.False(t, upstreamBillingProbeTargetIsOfficialAPI("https://moonshot.cn.evil.example/v1"))
require.False(t, upstreamBillingProbeTargetIsOfficialAPI("https://kimi.example/v1"))
require.False(t, upstreamBillingProbeTargetIsOfficialAPI("https://nottypesafe.ai"))
require.False(t, upstreamBillingProbeTargetIsOfficialAPI("https://notbigmodel.cn"))
require.False(t, upstreamBillingProbeTargetIsOfficialAPI("https://deepseek.example.com"))
}
@@ -276,3 +282,18 @@ func TestUpstreamBillingProbeSetAccountEnabledAcceptsGrokAPIKey(t *testing.T) {
err := svc.SetAccountEnabled(context.Background(), grokOAuth.ID, true)
require.ErrorIs(t, err, ErrUpstreamBillingProbeAccountInvalid)
}
// 回归:创建表单对全部 API-key 平台默认开启自动探测;TypeSafe 账号带默认开关创建
// 不能被 UPSTREAM_BILLING_PROBE_ACCOUNT_INVALID 拒绝。
func TestBuildAccountForCreateAcceptsTypeSafeAPIKeyWithProbeEnabled(t *testing.T) {
enabled := true
account, err := buildAccountForCreate(&CreateAccountInput{
Name: "typesafe",
Platform: PlatformTypeSafe,
Type: AccountTypeAPIKey,
Credentials: map[string]any{"api_key": "ts-key", "base_url": "https://api.typesafe.ai"},
ProbeEnabled: &enabled,
}, map[string]any{})
require.NoError(t, err)
require.Equal(t, true, account.Extra[UpstreamBillingProbeEnabledExtraKey])
}