2025-12-10 20:52:44 +08:00
|
|
|
|
import client from '../client'
|
2026-01-10 18:43:53 +08:00
|
|
|
|
import type { EndpointAPIKey, AllowedModels } from './types'
|
2026-04-17 18:22:41 +08:00
|
|
|
|
import type { QuotaStatusSnapshot } from './types'
|
2025-12-10 20:52:44 +08:00
|
|
|
|
|
2026-01-22 23:25:51 +08:00
|
|
|
|
// Re-export types for convenience
|
|
|
|
|
|
export type { EndpointAPIKey, AllowedModels }
|
|
|
|
|
|
|
2026-04-05 20:23:16 +08:00
|
|
|
|
interface KeyRequestOptions {
|
|
|
|
|
|
timeout?: number
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2025-12-10 20:52:44 +08:00
|
|
|
|
/**
|
|
|
|
|
|
* 能力定义类型
|
|
|
|
|
|
*/
|
|
|
|
|
|
export interface CapabilityDefinition {
|
|
|
|
|
|
name: string
|
|
|
|
|
|
display_name: string
|
|
|
|
|
|
description: string
|
|
|
|
|
|
match_mode: 'exclusive' | 'compatible'
|
|
|
|
|
|
config_mode?: 'user_configurable' | 'auto_detect' | 'request_param'
|
|
|
|
|
|
short_name?: string
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
|
* 模型支持的能力响应类型
|
|
|
|
|
|
*/
|
|
|
|
|
|
export interface ModelCapabilitiesResponse {
|
|
|
|
|
|
model: string
|
|
|
|
|
|
global_model_id?: string
|
|
|
|
|
|
global_model_name?: string
|
|
|
|
|
|
supported_capabilities: string[]
|
|
|
|
|
|
capability_details: CapabilityDefinition[]
|
|
|
|
|
|
error?: string
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
|
* 获取所有能力定义
|
|
|
|
|
|
*/
|
|
|
|
|
|
export async function getAllCapabilities(): Promise<CapabilityDefinition[]> {
|
|
|
|
|
|
const response = await client.get('/api/capabilities')
|
|
|
|
|
|
return response.data.capabilities
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
|
* 获取用户可配置的能力列表
|
|
|
|
|
|
*/
|
|
|
|
|
|
export async function getUserConfigurableCapabilities(): Promise<CapabilityDefinition[]> {
|
|
|
|
|
|
const response = await client.get('/api/capabilities/user-configurable')
|
|
|
|
|
|
return response.data.capabilities
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
|
* 获取指定模型支持的能力列表
|
|
|
|
|
|
*/
|
|
|
|
|
|
export async function getModelCapabilities(modelName: string): Promise<ModelCapabilitiesResponse> {
|
|
|
|
|
|
const response = await client.get(`/api/capabilities/model/${encodeURIComponent(modelName)}`)
|
|
|
|
|
|
return response.data
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2025-12-29 17:14:26 +08:00
|
|
|
|
/**
|
|
|
|
|
|
* 获取完整的 API Key(用于查看和复制)
|
|
|
|
|
|
*/
|
2026-01-30 02:43:50 +08:00
|
|
|
|
export interface RevealKeyResult {
|
2026-04-17 12:57:06 +08:00
|
|
|
|
auth_type: 'api_key' | 'service_account' | 'oauth' | 'bearer'
|
2026-01-30 02:43:50 +08:00
|
|
|
|
api_key?: string
|
2026-02-06 21:52:22 +08:00
|
|
|
|
refresh_token?: string
|
2026-02-22 00:43:41 +08:00
|
|
|
|
auth_config?: string | Record<string, unknown>
|
2026-01-30 02:43:50 +08:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
export async function revealEndpointKey(keyId: string): Promise<RevealKeyResult> {
|
2025-12-29 17:14:26 +08:00
|
|
|
|
const response = await client.get(`/api/admin/endpoints/keys/${keyId}/reveal`)
|
|
|
|
|
|
return response.data
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2026-02-09 01:05:48 +08:00
|
|
|
|
/**
|
|
|
|
|
|
* 导出 OAuth Key 凭据(扁平 JSON,用于跨实例迁移)
|
|
|
|
|
|
*/
|
2026-02-22 00:43:41 +08:00
|
|
|
|
export async function exportKey(keyId: string): Promise<Record<string, unknown>> {
|
2026-02-09 01:05:48 +08:00
|
|
|
|
const response = await client.get(`/api/admin/endpoints/keys/${keyId}/export`)
|
|
|
|
|
|
return response.data
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2025-12-10 20:52:44 +08:00
|
|
|
|
/**
|
2026-01-10 18:43:53 +08:00
|
|
|
|
* 删除 Key
|
2025-12-10 20:52:44 +08:00
|
|
|
|
*/
|
|
|
|
|
|
export async function deleteEndpointKey(keyId: string): Promise<{ message: string }> {
|
|
|
|
|
|
const response = await client.delete(`/api/admin/endpoints/keys/${keyId}`)
|
|
|
|
|
|
return response.data
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2026-03-07 03:49:44 +08:00
|
|
|
|
/**
|
|
|
|
|
|
* 批量删除 Keys
|
|
|
|
|
|
*/
|
|
|
|
|
|
export interface BatchDeleteKeysResult {
|
|
|
|
|
|
success_count: number
|
|
|
|
|
|
failed_count: number
|
|
|
|
|
|
failed: Array<{ id: string; error: string }>
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
export async function batchDeleteEndpointKeys(ids: string[]): Promise<BatchDeleteKeysResult> {
|
|
|
|
|
|
const response = await client.post('/api/admin/endpoints/keys/batch-delete', { ids })
|
|
|
|
|
|
return response.data
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2026-01-10 18:43:53 +08:00
|
|
|
|
|
|
|
|
|
|
// ========== Provider 级别的 Keys API ==========
|
|
|
|
|
|
|
|
|
|
|
|
|
2025-12-10 20:52:44 +08:00
|
|
|
|
/**
|
2026-01-10 18:43:53 +08:00
|
|
|
|
* 获取 Provider 的所有 Keys
|
2025-12-10 20:52:44 +08:00
|
|
|
|
*/
|
2026-05-16 12:52:49 +08:00
|
|
|
|
export interface ProviderKeysPageResponse {
|
|
|
|
|
|
total: number
|
|
|
|
|
|
page: number
|
|
|
|
|
|
page_size: number
|
|
|
|
|
|
keys: EndpointAPIKey[]
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
export interface ProviderKeysPageQuery {
|
|
|
|
|
|
page?: number
|
|
|
|
|
|
page_size?: number
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2026-07-17 19:20:16 +08:00
|
|
|
|
type ProviderKeysPagePayload = ProviderKeysPageResponse | EndpointAPIKey[]
|
|
|
|
|
|
|
|
|
|
|
|
function normalizeProviderKeysPage(
|
|
|
|
|
|
value: ProviderKeysPagePayload,
|
|
|
|
|
|
page: number,
|
|
|
|
|
|
pageSize: number,
|
|
|
|
|
|
): ProviderKeysPageResponse {
|
|
|
|
|
|
if (Array.isArray(value)) {
|
|
|
|
|
|
const start = value.length > pageSize ? (page - 1) * pageSize : 0
|
|
|
|
|
|
const keys = value.slice(start, start + pageSize)
|
|
|
|
|
|
return {
|
|
|
|
|
|
total: value.length,
|
|
|
|
|
|
page,
|
|
|
|
|
|
page_size: pageSize,
|
|
|
|
|
|
keys,
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
const keys = Array.isArray(value.keys) ? value.keys : []
|
|
|
|
|
|
return {
|
|
|
|
|
|
total: typeof value.total === 'number' && Number.isFinite(value.total)
|
|
|
|
|
|
? value.total
|
|
|
|
|
|
: keys.length,
|
|
|
|
|
|
page: typeof value.page === 'number' && Number.isFinite(value.page)
|
|
|
|
|
|
? value.page
|
|
|
|
|
|
: page,
|
|
|
|
|
|
page_size: typeof value.page_size === 'number' && Number.isFinite(value.page_size)
|
|
|
|
|
|
? value.page_size
|
|
|
|
|
|
: pageSize,
|
|
|
|
|
|
keys,
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2026-05-16 12:52:49 +08:00
|
|
|
|
export async function getProviderKeysPage(
|
|
|
|
|
|
providerId: string,
|
|
|
|
|
|
params: ProviderKeysPageQuery = {},
|
|
|
|
|
|
): Promise<ProviderKeysPageResponse> {
|
|
|
|
|
|
const page = params.page ?? 1
|
|
|
|
|
|
const pageSize = params.page_size ?? 20
|
2026-07-17 19:20:16 +08:00
|
|
|
|
const response = await client.get<ProviderKeysPagePayload>(
|
2026-05-16 12:52:49 +08:00
|
|
|
|
`/api/admin/endpoints/providers/${providerId}/keys`,
|
|
|
|
|
|
{ params: { page, page_size: pageSize } },
|
|
|
|
|
|
)
|
2026-07-17 19:20:16 +08:00
|
|
|
|
return normalizeProviderKeysPage(response.data, page, pageSize)
|
2026-05-16 12:52:49 +08:00
|
|
|
|
}
|
|
|
|
|
|
|
2026-01-10 18:43:53 +08:00
|
|
|
|
export async function getProviderKeys(providerId: string): Promise<EndpointAPIKey[]> {
|
2026-02-27 15:07:44 +08:00
|
|
|
|
// 后端默认 limit=100,这里主动分页拉取,避免账号数 >100 时前端被截断
|
|
|
|
|
|
const pageSize = 1000
|
|
|
|
|
|
let skip = 0
|
|
|
|
|
|
const allKeys: EndpointAPIKey[] = []
|
|
|
|
|
|
|
|
|
|
|
|
while (true) {
|
|
|
|
|
|
const response = await client.get(`/api/admin/endpoints/providers/${providerId}/keys`, {
|
|
|
|
|
|
params: { skip, limit: pageSize },
|
|
|
|
|
|
})
|
|
|
|
|
|
|
|
|
|
|
|
const batch = Array.isArray(response.data) ? (response.data as EndpointAPIKey[]) : []
|
|
|
|
|
|
allKeys.push(...batch)
|
|
|
|
|
|
|
|
|
|
|
|
if (batch.length < pageSize) break
|
|
|
|
|
|
skip += pageSize
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
return allKeys
|
2026-01-10 18:43:53 +08:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
|
* 为 Provider 添加 Key
|
|
|
|
|
|
*/
|
|
|
|
|
|
export async function addProviderKey(
|
|
|
|
|
|
providerId: string,
|
|
|
|
|
|
data: {
|
|
|
|
|
|
api_formats: string[] // 支持的 API 格式列表(必填)
|
|
|
|
|
|
api_key: string
|
2026-04-29 15:46:50 +08:00
|
|
|
|
auth_type?: 'api_key' | 'service_account' | 'oauth' | 'bearer' // 认证类型
|
|
|
|
|
|
auth_type_by_format?: Record<string, 'api_key' | 'bearer'> | null
|
2026-05-03 00:49:22 +08:00
|
|
|
|
allow_auth_channel_mismatch_formats?: string[] | null
|
2026-02-22 00:43:41 +08:00
|
|
|
|
auth_config?: Record<string, unknown> // 认证配置(Vertex AI Service Account JSON)
|
2026-01-10 18:43:53 +08:00
|
|
|
|
name: string
|
|
|
|
|
|
rate_multipliers?: Record<string, number> | null // 按 API 格式的成本倍率
|
|
|
|
|
|
internal_priority?: number
|
|
|
|
|
|
rpm_limit?: number | null // RPM 限制(留空=自适应模式)
|
2026-05-03 01:55:23 +08:00
|
|
|
|
concurrent_limit?: number | null // 并发请求上限(留空或 0=不限制)
|
2026-01-10 18:43:53 +08:00
|
|
|
|
cache_ttl_minutes?: number
|
|
|
|
|
|
max_probe_interval_minutes?: number
|
|
|
|
|
|
allowed_models?: AllowedModels
|
|
|
|
|
|
capabilities?: Record<string, boolean>
|
|
|
|
|
|
note?: string
|
2026-01-14 13:12:19 +08:00
|
|
|
|
auto_fetch_models?: boolean // 是否启用自动获取模型
|
2026-01-28 00:04:47 +08:00
|
|
|
|
model_include_patterns?: string[] // 模型包含规则
|
|
|
|
|
|
model_exclude_patterns?: string[] // 模型排除规则
|
2026-01-10 18:43:53 +08:00
|
|
|
|
}
|
|
|
|
|
|
): Promise<EndpointAPIKey> {
|
|
|
|
|
|
const response = await client.post(`/api/admin/endpoints/providers/${providerId}/keys`, data)
|
|
|
|
|
|
return response.data
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
|
* 更新 Key
|
|
|
|
|
|
*/
|
|
|
|
|
|
export async function updateProviderKey(
|
|
|
|
|
|
keyId: string,
|
|
|
|
|
|
data: Partial<{
|
|
|
|
|
|
api_formats: string[] // 支持的 API 格式列表
|
|
|
|
|
|
api_key: string
|
2026-04-17 12:57:06 +08:00
|
|
|
|
auth_type: 'api_key' | 'service_account' | 'oauth' | 'bearer' // 认证类型
|
2026-04-29 15:46:50 +08:00
|
|
|
|
auth_type_by_format: Record<string, 'api_key' | 'bearer'> | null
|
2026-05-03 00:49:22 +08:00
|
|
|
|
allow_auth_channel_mismatch_formats: string[] | null
|
2026-02-22 00:43:41 +08:00
|
|
|
|
auth_config: Record<string, unknown> // 认证配置(Vertex AI Service Account JSON)
|
2026-01-10 18:43:53 +08:00
|
|
|
|
name: string
|
|
|
|
|
|
rate_multipliers: Record<string, number> | null // 按 API 格式的成本倍率
|
|
|
|
|
|
internal_priority: number
|
2026-01-16 17:53:27 +08:00
|
|
|
|
global_priority_by_format: Record<string, number> | null // 按 API 格式的全局优先级
|
2026-01-10 18:43:53 +08:00
|
|
|
|
rpm_limit: number | null // RPM 限制(留空=自适应模式)
|
2026-05-03 01:55:23 +08:00
|
|
|
|
concurrent_limit: number | null // 并发请求上限(留空或 0=不限制)
|
2026-01-10 18:43:53 +08:00
|
|
|
|
cache_ttl_minutes: number
|
|
|
|
|
|
max_probe_interval_minutes: number
|
|
|
|
|
|
allowed_models: AllowedModels
|
2026-01-14 13:12:19 +08:00
|
|
|
|
locked_models: string[] // 被锁定的模型列表
|
2026-01-10 18:43:53 +08:00
|
|
|
|
capabilities: Record<string, boolean> | null
|
|
|
|
|
|
is_active: boolean
|
|
|
|
|
|
note: string
|
2026-01-14 13:12:19 +08:00
|
|
|
|
auto_fetch_models: boolean // 是否启用自动获取模型
|
2026-01-28 00:04:47 +08:00
|
|
|
|
model_include_patterns: string[] // 模型包含规则
|
|
|
|
|
|
model_exclude_patterns: string[] // 模型排除规则
|
2026-02-09 01:05:48 +08:00
|
|
|
|
proxy: import('./types').ProxyConfig | null // Key 级别代理配置
|
2026-04-05 20:23:16 +08:00
|
|
|
|
}>,
|
|
|
|
|
|
requestOptions?: KeyRequestOptions,
|
2026-01-10 18:43:53 +08:00
|
|
|
|
): Promise<EndpointAPIKey> {
|
2026-04-05 20:23:16 +08:00
|
|
|
|
const response = await client.put(
|
|
|
|
|
|
`/api/admin/endpoints/keys/${keyId}`,
|
|
|
|
|
|
data,
|
|
|
|
|
|
requestOptions,
|
|
|
|
|
|
)
|
2025-12-10 20:52:44 +08:00
|
|
|
|
return response.data
|
|
|
|
|
|
}
|
2026-02-05 18:09:14 +08:00
|
|
|
|
|
|
|
|
|
|
/**
|
2026-02-06 16:37:06 +08:00
|
|
|
|
* 清除 Key 的 OAuth 失效标记
|
|
|
|
|
|
*/
|
|
|
|
|
|
export async function clearOAuthInvalid(keyId: string): Promise<{ message: string }> {
|
|
|
|
|
|
const response = await client.post(`/api/admin/endpoints/keys/${keyId}/clear-oauth-invalid`)
|
|
|
|
|
|
return response.data
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2026-05-07 03:23:20 +08:00
|
|
|
|
/**
|
|
|
|
|
|
* 重置 Key 的当前周期统计起点(Codex 号池)
|
|
|
|
|
|
*/
|
|
|
|
|
|
export async function resetProviderKeyCycleStats(keyId: string): Promise<{
|
|
|
|
|
|
message: string
|
|
|
|
|
|
reset_at: number
|
|
|
|
|
|
windows: number
|
|
|
|
|
|
}> {
|
|
|
|
|
|
const response = await client.post(`/api/admin/endpoints/keys/${keyId}/reset-cycle-stats`)
|
|
|
|
|
|
return response.data
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2026-02-06 16:37:06 +08:00
|
|
|
|
/**
|
|
|
|
|
|
* 刷新 Provider 的所有 Key 限额信息(Codex / Antigravity)
|
2026-02-05 18:09:14 +08:00
|
|
|
|
*/
|
|
|
|
|
|
export interface RefreshQuotaResult {
|
|
|
|
|
|
success: number
|
|
|
|
|
|
failed: number
|
|
|
|
|
|
total: number
|
|
|
|
|
|
results: Array<{
|
|
|
|
|
|
key_id: string
|
|
|
|
|
|
key_name: string
|
2026-04-17 18:22:41 +08:00
|
|
|
|
status:
|
|
|
|
|
|
| 'success'
|
|
|
|
|
|
| 'no_metadata'
|
|
|
|
|
|
| 'quota_exhausted'
|
|
|
|
|
|
| 'workspace_deactivated'
|
|
|
|
|
|
| 'auth_invalid'
|
|
|
|
|
|
| 'forbidden'
|
|
|
|
|
|
| 'banned'
|
|
|
|
|
|
| 'error'
|
|
|
|
|
|
// provider 级 bucket 数据;前端应按当前 provider_type 包装回 upstream_metadata.<provider_type>
|
2026-02-22 00:43:41 +08:00
|
|
|
|
metadata?: Record<string, unknown>
|
2026-04-17 18:22:41 +08:00
|
|
|
|
quota_snapshot?: QuotaStatusSnapshot
|
2026-02-05 18:09:14 +08:00
|
|
|
|
message?: string
|
|
|
|
|
|
status_code?: number
|
|
|
|
|
|
}>
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2026-03-03 11:32:41 +08:00
|
|
|
|
export async function refreshProviderQuota(
|
|
|
|
|
|
providerId: string,
|
|
|
|
|
|
keyIds?: string[],
|
|
|
|
|
|
): Promise<RefreshQuotaResult> {
|
|
|
|
|
|
const body = keyIds && keyIds.length > 0 ? { key_ids: keyIds } : undefined
|
2026-03-07 02:16:03 +08:00
|
|
|
|
const response = await client.post(
|
|
|
|
|
|
`/api/admin/endpoints/providers/${providerId}/refresh-quota`,
|
|
|
|
|
|
body,
|
|
|
|
|
|
{ timeout: 5 * 60 * 1000 },
|
|
|
|
|
|
)
|
2026-02-05 18:09:14 +08:00
|
|
|
|
return response.data
|
|
|
|
|
|
}
|
2026-02-09 01:05:48 +08:00
|
|
|
|
|
2026-07-04 06:10:53 +08:00
|
|
|
|
export interface ConsumeCodexResetCreditPayload {
|
|
|
|
|
|
idempotency_key: string
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
export interface ConsumeCodexResetCreditResult {
|
|
|
|
|
|
key_id: string
|
|
|
|
|
|
status: 'success' | 'noop' | 'unknown' | 'error' | string
|
|
|
|
|
|
outcome:
|
|
|
|
|
|
| 'reset'
|
|
|
|
|
|
| 'already_redeemed'
|
|
|
|
|
|
| 'nothing_to_reset'
|
|
|
|
|
|
| 'no_credit'
|
|
|
|
|
|
| 'unknown'
|
|
|
|
|
|
| 'error'
|
|
|
|
|
|
| string
|
|
|
|
|
|
idempotency_key: string
|
|
|
|
|
|
refresh_status?: 'success' | 'failed' | string
|
|
|
|
|
|
refresh_error?: string | null
|
|
|
|
|
|
metadata?: Record<string, unknown>
|
|
|
|
|
|
quota_snapshot?: QuotaStatusSnapshot
|
|
|
|
|
|
message?: string
|
|
|
|
|
|
status_code?: number
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
export async function consumeCodexResetCredit(
|
|
|
|
|
|
keyId: string,
|
|
|
|
|
|
payload: ConsumeCodexResetCreditPayload,
|
|
|
|
|
|
): Promise<ConsumeCodexResetCreditResult> {
|
|
|
|
|
|
const response = await client.post(
|
|
|
|
|
|
`/api/admin/endpoints/keys/${keyId}/codex-reset-credit/consume`,
|
|
|
|
|
|
payload,
|
|
|
|
|
|
{ timeout: 5 * 60 * 1000 },
|
|
|
|
|
|
)
|
|
|
|
|
|
return response.data
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2026-02-09 01:05:48 +08:00
|
|
|
|
/**
|
|
|
|
|
|
* 批量导入 OAuth 凭据(通用)
|
|
|
|
|
|
* 支持的 Provider 类型:Codex、Antigravity、GeminiCli、ClaudeCode、Kiro
|
|
|
|
|
|
*/
|
|
|
|
|
|
export interface BatchImportResultItem {
|
|
|
|
|
|
index: number
|
|
|
|
|
|
status: 'success' | 'error'
|
|
|
|
|
|
key_id?: string
|
|
|
|
|
|
key_name?: string
|
|
|
|
|
|
auth_method?: string
|
|
|
|
|
|
error?: string
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
export interface BatchImportResult {
|
|
|
|
|
|
total: number
|
|
|
|
|
|
success: number
|
|
|
|
|
|
failed: number
|
|
|
|
|
|
results: BatchImportResultItem[]
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
export async function batchImportOAuth(
|
|
|
|
|
|
providerId: string,
|
2026-02-09 02:56:21 +08:00
|
|
|
|
credentials: string,
|
|
|
|
|
|
proxyNodeId?: string
|
2026-02-09 01:05:48 +08:00
|
|
|
|
): Promise<BatchImportResult> {
|
|
|
|
|
|
const response = await client.post(`/api/admin/provider-oauth/providers/${providerId}/batch-import`, {
|
|
|
|
|
|
credentials,
|
2026-02-09 02:56:21 +08:00
|
|
|
|
proxy_node_id: proxyNodeId || undefined,
|
2026-02-09 01:05:48 +08:00
|
|
|
|
})
|
|
|
|
|
|
return response.data
|
|
|
|
|
|
}
|