Merge pull request #517 from touwaeriol/fix/upstream-baseurl
refactor(upstream): replace upstream account type with apikey + auto-append base_url
This commit is contained in:
@@ -1 +1 @@
|
|||||||
0.1.70
|
0.1.74.7
|
||||||
|
|||||||
@@ -482,7 +482,7 @@ func (h *GatewayHandler) Messages(c *gin.Context) {
|
|||||||
if switchCount > 0 {
|
if switchCount > 0 {
|
||||||
requestCtx = context.WithValue(requestCtx, ctxkey.AccountSwitchCount, switchCount)
|
requestCtx = context.WithValue(requestCtx, ctxkey.AccountSwitchCount, switchCount)
|
||||||
}
|
}
|
||||||
if account.Platform == service.PlatformAntigravity {
|
if account.Platform == service.PlatformAntigravity && account.Type != service.AccountTypeAPIKey {
|
||||||
result, err = h.antigravityGatewayService.Forward(requestCtx, c, account, body, hasBoundSession)
|
result, err = h.antigravityGatewayService.Forward(requestCtx, c, account, body, hasBoundSession)
|
||||||
} else {
|
} else {
|
||||||
result, err = h.gatewayService.Forward(requestCtx, c, account, parsedReq)
|
result, err = h.gatewayService.Forward(requestCtx, c, account, parsedReq)
|
||||||
|
|||||||
@@ -410,7 +410,7 @@ func (h *GatewayHandler) GeminiV1BetaModels(c *gin.Context) {
|
|||||||
if switchCount > 0 {
|
if switchCount > 0 {
|
||||||
requestCtx = context.WithValue(requestCtx, ctxkey.AccountSwitchCount, switchCount)
|
requestCtx = context.WithValue(requestCtx, ctxkey.AccountSwitchCount, switchCount)
|
||||||
}
|
}
|
||||||
if account.Platform == service.PlatformAntigravity {
|
if account.Platform == service.PlatformAntigravity && account.Type != service.AccountTypeAPIKey {
|
||||||
result, err = h.antigravityGatewayService.ForwardGemini(requestCtx, c, account, modelName, action, stream, body, hasBoundSession)
|
result, err = h.antigravityGatewayService.ForwardGemini(requestCtx, c, account, modelName, action, stream, body, hasBoundSession)
|
||||||
} else {
|
} else {
|
||||||
result, err = h.geminiCompatService.ForwardNative(requestCtx, c, account, modelName, action, stream, body)
|
result, err = h.geminiCompatService.ForwardNative(requestCtx, c, account, modelName, action, stream, body)
|
||||||
|
|||||||
@@ -425,6 +425,22 @@ func (a *Account) GetBaseURL() string {
|
|||||||
if baseURL == "" {
|
if baseURL == "" {
|
||||||
return "https://api.anthropic.com"
|
return "https://api.anthropic.com"
|
||||||
}
|
}
|
||||||
|
if a.Platform == PlatformAntigravity {
|
||||||
|
return strings.TrimRight(baseURL, "/") + "/antigravity"
|
||||||
|
}
|
||||||
|
return baseURL
|
||||||
|
}
|
||||||
|
|
||||||
|
// GetGeminiBaseURL 返回 Gemini 兼容端点的 base URL。
|
||||||
|
// Antigravity 平台的 APIKey 账号自动拼接 /antigravity。
|
||||||
|
func (a *Account) GetGeminiBaseURL(defaultBaseURL string) string {
|
||||||
|
baseURL := strings.TrimSpace(a.GetCredential("base_url"))
|
||||||
|
if baseURL == "" {
|
||||||
|
return defaultBaseURL
|
||||||
|
}
|
||||||
|
if a.Platform == PlatformAntigravity && a.Type == AccountTypeAPIKey {
|
||||||
|
return strings.TrimRight(baseURL, "/") + "/antigravity"
|
||||||
|
}
|
||||||
return baseURL
|
return baseURL
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
160
backend/internal/service/account_base_url_test.go
Normal file
160
backend/internal/service/account_base_url_test.go
Normal file
@@ -0,0 +1,160 @@
|
|||||||
|
//go:build unit
|
||||||
|
|
||||||
|
package service
|
||||||
|
|
||||||
|
import (
|
||||||
|
"testing"
|
||||||
|
)
|
||||||
|
|
||||||
|
func TestGetBaseURL(t *testing.T) {
|
||||||
|
tests := []struct {
|
||||||
|
name string
|
||||||
|
account Account
|
||||||
|
expected string
|
||||||
|
}{
|
||||||
|
{
|
||||||
|
name: "non-apikey type returns empty",
|
||||||
|
account: Account{
|
||||||
|
Type: AccountTypeOAuth,
|
||||||
|
Platform: PlatformAnthropic,
|
||||||
|
},
|
||||||
|
expected: "",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "apikey without base_url returns default anthropic",
|
||||||
|
account: Account{
|
||||||
|
Type: AccountTypeAPIKey,
|
||||||
|
Platform: PlatformAnthropic,
|
||||||
|
Credentials: map[string]any{},
|
||||||
|
},
|
||||||
|
expected: "https://api.anthropic.com",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "apikey with custom base_url",
|
||||||
|
account: Account{
|
||||||
|
Type: AccountTypeAPIKey,
|
||||||
|
Platform: PlatformAnthropic,
|
||||||
|
Credentials: map[string]any{"base_url": "https://custom.example.com"},
|
||||||
|
},
|
||||||
|
expected: "https://custom.example.com",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "antigravity apikey auto-appends /antigravity",
|
||||||
|
account: Account{
|
||||||
|
Type: AccountTypeAPIKey,
|
||||||
|
Platform: PlatformAntigravity,
|
||||||
|
Credentials: map[string]any{"base_url": "https://upstream.example.com"},
|
||||||
|
},
|
||||||
|
expected: "https://upstream.example.com/antigravity",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "antigravity apikey trims trailing slash before appending",
|
||||||
|
account: Account{
|
||||||
|
Type: AccountTypeAPIKey,
|
||||||
|
Platform: PlatformAntigravity,
|
||||||
|
Credentials: map[string]any{"base_url": "https://upstream.example.com/"},
|
||||||
|
},
|
||||||
|
expected: "https://upstream.example.com/antigravity",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "antigravity non-apikey returns empty",
|
||||||
|
account: Account{
|
||||||
|
Type: AccountTypeOAuth,
|
||||||
|
Platform: PlatformAntigravity,
|
||||||
|
Credentials: map[string]any{"base_url": "https://upstream.example.com"},
|
||||||
|
},
|
||||||
|
expected: "",
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, tt := range tests {
|
||||||
|
t.Run(tt.name, func(t *testing.T) {
|
||||||
|
result := tt.account.GetBaseURL()
|
||||||
|
if result != tt.expected {
|
||||||
|
t.Errorf("GetBaseURL() = %q, want %q", result, tt.expected)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestGetGeminiBaseURL(t *testing.T) {
|
||||||
|
const defaultGeminiURL = "https://generativelanguage.googleapis.com"
|
||||||
|
|
||||||
|
tests := []struct {
|
||||||
|
name string
|
||||||
|
account Account
|
||||||
|
expected string
|
||||||
|
}{
|
||||||
|
{
|
||||||
|
name: "apikey without base_url returns default",
|
||||||
|
account: Account{
|
||||||
|
Type: AccountTypeAPIKey,
|
||||||
|
Platform: PlatformGemini,
|
||||||
|
Credentials: map[string]any{},
|
||||||
|
},
|
||||||
|
expected: defaultGeminiURL,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "apikey with custom base_url",
|
||||||
|
account: Account{
|
||||||
|
Type: AccountTypeAPIKey,
|
||||||
|
Platform: PlatformGemini,
|
||||||
|
Credentials: map[string]any{"base_url": "https://custom-gemini.example.com"},
|
||||||
|
},
|
||||||
|
expected: "https://custom-gemini.example.com",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "antigravity apikey auto-appends /antigravity",
|
||||||
|
account: Account{
|
||||||
|
Type: AccountTypeAPIKey,
|
||||||
|
Platform: PlatformAntigravity,
|
||||||
|
Credentials: map[string]any{"base_url": "https://upstream.example.com"},
|
||||||
|
},
|
||||||
|
expected: "https://upstream.example.com/antigravity",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "antigravity apikey trims trailing slash",
|
||||||
|
account: Account{
|
||||||
|
Type: AccountTypeAPIKey,
|
||||||
|
Platform: PlatformAntigravity,
|
||||||
|
Credentials: map[string]any{"base_url": "https://upstream.example.com/"},
|
||||||
|
},
|
||||||
|
expected: "https://upstream.example.com/antigravity",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "antigravity oauth does NOT append /antigravity",
|
||||||
|
account: Account{
|
||||||
|
Type: AccountTypeOAuth,
|
||||||
|
Platform: PlatformAntigravity,
|
||||||
|
Credentials: map[string]any{"base_url": "https://upstream.example.com"},
|
||||||
|
},
|
||||||
|
expected: "https://upstream.example.com",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "oauth without base_url returns default",
|
||||||
|
account: Account{
|
||||||
|
Type: AccountTypeOAuth,
|
||||||
|
Platform: PlatformAntigravity,
|
||||||
|
Credentials: map[string]any{},
|
||||||
|
},
|
||||||
|
expected: defaultGeminiURL,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "nil credentials returns default",
|
||||||
|
account: Account{
|
||||||
|
Type: AccountTypeAPIKey,
|
||||||
|
Platform: PlatformGemini,
|
||||||
|
},
|
||||||
|
expected: defaultGeminiURL,
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, tt := range tests {
|
||||||
|
t.Run(tt.name, func(t *testing.T) {
|
||||||
|
result := tt.account.GetGeminiBaseURL(defaultGeminiURL)
|
||||||
|
if result != tt.expected {
|
||||||
|
t.Errorf("GetGeminiBaseURL() = %q, want %q", result, tt.expected)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -643,6 +643,7 @@ type TestConnectionResult struct {
|
|||||||
// TestConnection 测试 Antigravity 账号连接(非流式,无重试、无计费)
|
// TestConnection 测试 Antigravity 账号连接(非流式,无重试、无计费)
|
||||||
// 支持 Claude 和 Gemini 两种协议,根据 modelID 前缀自动选择
|
// 支持 Claude 和 Gemini 两种协议,根据 modelID 前缀自动选择
|
||||||
func (s *AntigravityGatewayService) TestConnection(ctx context.Context, account *Account, modelID string) (*TestConnectionResult, error) {
|
func (s *AntigravityGatewayService) TestConnection(ctx context.Context, account *Account, modelID string) (*TestConnectionResult, error) {
|
||||||
|
|
||||||
// 获取 token
|
// 获取 token
|
||||||
if s.tokenProvider == nil {
|
if s.tokenProvider == nil {
|
||||||
return nil, errors.New("antigravity token provider not configured")
|
return nil, errors.New("antigravity token provider not configured")
|
||||||
@@ -969,6 +970,7 @@ func isModelNotFoundError(statusCode int, body []byte) bool {
|
|||||||
// └─ 失败 → 设置模型限流 + 清除粘性绑定 → 切换账号
|
// └─ 失败 → 设置模型限流 + 清除粘性绑定 → 切换账号
|
||||||
func (s *AntigravityGatewayService) Forward(ctx context.Context, c *gin.Context, account *Account, body []byte, isStickySession bool) (*ForwardResult, error) {
|
func (s *AntigravityGatewayService) Forward(ctx context.Context, c *gin.Context, account *Account, body []byte, isStickySession bool) (*ForwardResult, error) {
|
||||||
startTime := time.Now()
|
startTime := time.Now()
|
||||||
|
|
||||||
sessionID := getSessionID(c)
|
sessionID := getSessionID(c)
|
||||||
prefix := logPrefix(sessionID, account.Name)
|
prefix := logPrefix(sessionID, account.Name)
|
||||||
|
|
||||||
@@ -1598,6 +1600,7 @@ func stripSignatureSensitiveBlocksFromClaudeRequest(req *antigravity.ClaudeReque
|
|||||||
// └─ 失败 → 设置模型限流 + 清除粘性绑定 → 切换账号
|
// └─ 失败 → 设置模型限流 + 清除粘性绑定 → 切换账号
|
||||||
func (s *AntigravityGatewayService) ForwardGemini(ctx context.Context, c *gin.Context, account *Account, originalModel string, action string, stream bool, body []byte, isStickySession bool) (*ForwardResult, error) {
|
func (s *AntigravityGatewayService) ForwardGemini(ctx context.Context, c *gin.Context, account *Account, originalModel string, action string, stream bool, body []byte, isStickySession bool) (*ForwardResult, error) {
|
||||||
startTime := time.Now()
|
startTime := time.Now()
|
||||||
|
|
||||||
sessionID := getSessionID(c)
|
sessionID := getSessionID(c)
|
||||||
prefix := logPrefix(sessionID, account.Name)
|
prefix := logPrefix(sessionID, account.Name)
|
||||||
|
|
||||||
|
|||||||
@@ -560,10 +560,7 @@ func (s *GeminiMessagesCompatService) Forward(ctx context.Context, c *gin.Contex
|
|||||||
return nil, "", errors.New("gemini api_key not configured")
|
return nil, "", errors.New("gemini api_key not configured")
|
||||||
}
|
}
|
||||||
|
|
||||||
baseURL := strings.TrimSpace(account.GetCredential("base_url"))
|
baseURL := account.GetGeminiBaseURL(geminicli.AIStudioBaseURL)
|
||||||
if baseURL == "" {
|
|
||||||
baseURL = geminicli.AIStudioBaseURL
|
|
||||||
}
|
|
||||||
normalizedBaseURL, err := s.validateUpstreamBaseURL(baseURL)
|
normalizedBaseURL, err := s.validateUpstreamBaseURL(baseURL)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, "", err
|
return nil, "", err
|
||||||
@@ -640,10 +637,7 @@ func (s *GeminiMessagesCompatService) Forward(ctx context.Context, c *gin.Contex
|
|||||||
return upstreamReq, "x-request-id", nil
|
return upstreamReq, "x-request-id", nil
|
||||||
} else {
|
} else {
|
||||||
// Mode 2: AI Studio API with OAuth (like API key mode, but using Bearer token)
|
// Mode 2: AI Studio API with OAuth (like API key mode, but using Bearer token)
|
||||||
baseURL := strings.TrimSpace(account.GetCredential("base_url"))
|
baseURL := account.GetGeminiBaseURL(geminicli.AIStudioBaseURL)
|
||||||
if baseURL == "" {
|
|
||||||
baseURL = geminicli.AIStudioBaseURL
|
|
||||||
}
|
|
||||||
normalizedBaseURL, err := s.validateUpstreamBaseURL(baseURL)
|
normalizedBaseURL, err := s.validateUpstreamBaseURL(baseURL)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, "", err
|
return nil, "", err
|
||||||
@@ -1026,10 +1020,7 @@ func (s *GeminiMessagesCompatService) ForwardNative(ctx context.Context, c *gin.
|
|||||||
return nil, "", errors.New("gemini api_key not configured")
|
return nil, "", errors.New("gemini api_key not configured")
|
||||||
}
|
}
|
||||||
|
|
||||||
baseURL := strings.TrimSpace(account.GetCredential("base_url"))
|
baseURL := account.GetGeminiBaseURL(geminicli.AIStudioBaseURL)
|
||||||
if baseURL == "" {
|
|
||||||
baseURL = geminicli.AIStudioBaseURL
|
|
||||||
}
|
|
||||||
normalizedBaseURL, err := s.validateUpstreamBaseURL(baseURL)
|
normalizedBaseURL, err := s.validateUpstreamBaseURL(baseURL)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, "", err
|
return nil, "", err
|
||||||
@@ -1097,10 +1088,7 @@ func (s *GeminiMessagesCompatService) ForwardNative(ctx context.Context, c *gin.
|
|||||||
return upstreamReq, "x-request-id", nil
|
return upstreamReq, "x-request-id", nil
|
||||||
} else {
|
} else {
|
||||||
// Mode 2: AI Studio API with OAuth (like API key mode, but using Bearer token)
|
// Mode 2: AI Studio API with OAuth (like API key mode, but using Bearer token)
|
||||||
baseURL := strings.TrimSpace(account.GetCredential("base_url"))
|
baseURL := account.GetGeminiBaseURL(geminicli.AIStudioBaseURL)
|
||||||
if baseURL == "" {
|
|
||||||
baseURL = geminicli.AIStudioBaseURL
|
|
||||||
}
|
|
||||||
normalizedBaseURL, err := s.validateUpstreamBaseURL(baseURL)
|
normalizedBaseURL, err := s.validateUpstreamBaseURL(baseURL)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, "", err
|
return nil, "", err
|
||||||
@@ -2420,10 +2408,7 @@ func (s *GeminiMessagesCompatService) ForwardAIStudioGET(ctx context.Context, ac
|
|||||||
return nil, errors.New("invalid path")
|
return nil, errors.New("invalid path")
|
||||||
}
|
}
|
||||||
|
|
||||||
baseURL := strings.TrimSpace(account.GetCredential("base_url"))
|
baseURL := account.GetGeminiBaseURL(geminicli.AIStudioBaseURL)
|
||||||
if baseURL == "" {
|
|
||||||
baseURL = geminicli.AIStudioBaseURL
|
|
||||||
}
|
|
||||||
normalizedBaseURL, err := s.validateUpstreamBaseURL(baseURL)
|
normalizedBaseURL, err := s.validateUpstreamBaseURL(baseURL)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
|
|||||||
11
backend/migrations/052_migrate_upstream_to_apikey.sql
Normal file
11
backend/migrations/052_migrate_upstream_to_apikey.sql
Normal file
@@ -0,0 +1,11 @@
|
|||||||
|
-- Migrate upstream accounts to apikey type
|
||||||
|
-- Background: upstream type is no longer needed. Antigravity platform APIKey accounts
|
||||||
|
-- with base_url pointing to an upstream sub2api instance can reuse the standard
|
||||||
|
-- APIKey forwarding path. GetBaseURL()/GetGeminiBaseURL() automatically appends
|
||||||
|
-- /antigravity for Antigravity platform APIKey accounts.
|
||||||
|
|
||||||
|
UPDATE accounts
|
||||||
|
SET type = 'apikey'
|
||||||
|
WHERE type = 'upstream'
|
||||||
|
AND platform = 'antigravity'
|
||||||
|
AND deleted_at IS NULL;
|
||||||
@@ -2289,9 +2289,9 @@ watch(
|
|||||||
watch(
|
watch(
|
||||||
[accountCategory, addMethod, antigravityAccountType],
|
[accountCategory, addMethod, antigravityAccountType],
|
||||||
([category, method, agType]) => {
|
([category, method, agType]) => {
|
||||||
// Antigravity upstream 类型
|
// Antigravity upstream 类型(实际创建为 apikey)
|
||||||
if (form.platform === 'antigravity' && agType === 'upstream') {
|
if (form.platform === 'antigravity' && agType === 'upstream') {
|
||||||
form.type = 'upstream'
|
form.type = 'apikey'
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
if (category === 'oauth-based') {
|
if (category === 'oauth-based') {
|
||||||
@@ -2714,7 +2714,8 @@ const handleSubmit = async () => {
|
|||||||
|
|
||||||
submitting.value = true
|
submitting.value = true
|
||||||
try {
|
try {
|
||||||
await createAccountAndFinish(form.platform, 'upstream', credentials)
|
const extra = mixedScheduling.value ? { mixed_scheduling: true } : undefined
|
||||||
|
await createAccountAndFinish(form.platform, 'apikey', credentials, extra)
|
||||||
} catch (error: any) {
|
} catch (error: any) {
|
||||||
appStore.showError(error.response?.data?.detail || t('admin.accounts.failedToCreate'))
|
appStore.showError(error.response?.data?.detail || t('admin.accounts.failedToCreate'))
|
||||||
} finally {
|
} finally {
|
||||||
|
|||||||
@@ -364,6 +364,30 @@
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
<!-- Upstream fields (only for upstream type) -->
|
||||||
|
<div v-if="account.type === 'upstream'" class="space-y-4">
|
||||||
|
<div>
|
||||||
|
<label class="input-label">{{ t('admin.accounts.upstream.baseUrl') }}</label>
|
||||||
|
<input
|
||||||
|
v-model="editBaseUrl"
|
||||||
|
type="text"
|
||||||
|
class="input"
|
||||||
|
placeholder="https://s.konstants.xyz"
|
||||||
|
/>
|
||||||
|
<p class="input-hint">{{ t('admin.accounts.upstream.baseUrlHint') }}</p>
|
||||||
|
</div>
|
||||||
|
<div>
|
||||||
|
<label class="input-label">{{ t('admin.accounts.upstream.apiKey') }}</label>
|
||||||
|
<input
|
||||||
|
v-model="editApiKey"
|
||||||
|
type="password"
|
||||||
|
class="input font-mono"
|
||||||
|
placeholder="sk-..."
|
||||||
|
/>
|
||||||
|
<p class="input-hint">{{ t('admin.accounts.leaveEmptyToKeep') }}</p>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
<!-- Antigravity model restriction (applies to all antigravity types) -->
|
<!-- Antigravity model restriction (applies to all antigravity types) -->
|
||||||
<!-- Antigravity 只支持模型映射模式,不支持白名单模式 -->
|
<!-- Antigravity 只支持模型映射模式,不支持白名单模式 -->
|
||||||
<div v-if="account.platform === 'antigravity'" class="border-t border-gray-200 pt-4 dark:border-dark-600">
|
<div v-if="account.platform === 'antigravity'" class="border-t border-gray-200 pt-4 dark:border-dark-600">
|
||||||
@@ -1244,6 +1268,9 @@ watch(
|
|||||||
} else {
|
} else {
|
||||||
selectedErrorCodes.value = []
|
selectedErrorCodes.value = []
|
||||||
}
|
}
|
||||||
|
} else if (newAccount.type === 'upstream' && newAccount.credentials) {
|
||||||
|
const credentials = newAccount.credentials as Record<string, unknown>
|
||||||
|
editBaseUrl.value = (credentials.base_url as string) || ''
|
||||||
} else {
|
} else {
|
||||||
const platformDefaultUrl =
|
const platformDefaultUrl =
|
||||||
newAccount.platform === 'openai'
|
newAccount.platform === 'openai'
|
||||||
@@ -1584,6 +1611,22 @@ const handleSubmit = async () => {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
updatePayload.credentials = newCredentials
|
||||||
|
} else if (props.account.type === 'upstream') {
|
||||||
|
const currentCredentials = (props.account.credentials as Record<string, unknown>) || {}
|
||||||
|
const newCredentials: Record<string, unknown> = { ...currentCredentials }
|
||||||
|
|
||||||
|
newCredentials.base_url = editBaseUrl.value.trim()
|
||||||
|
|
||||||
|
if (editApiKey.value.trim()) {
|
||||||
|
newCredentials.api_key = editApiKey.value.trim()
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!applyTempUnschedConfig(newCredentials)) {
|
||||||
|
submitting.value = false
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
updatePayload.credentials = newCredentials
|
updatePayload.credentials = newCredentials
|
||||||
} else {
|
} else {
|
||||||
// For oauth/setup-token types, only update intercept_warmup_requests if changed
|
// For oauth/setup-token types, only update intercept_warmup_requests if changed
|
||||||
|
|||||||
Reference in New Issue
Block a user