Sub2API v1.0 - AI API 网关(二开初始版本,基于上游 Wei-Shaw/sub2api)
Release / update-version (push) Has been cancelled
Release / build-frontend (push) Has been cancelled
Release / release (push) Has been cancelled
Release / sync-version-file (push) Has been cancelled
CI / shell (push) Canceled after 0s
CI / test (push) Canceled after 0s
CI / frontend (push) Canceled after 0s
CI / golangci-lint (push) Canceled after 0s
Security Scan / backend-security (push) Canceled after 0s
Security Scan / frontend-security (push) Canceled after 0s

This commit is contained in:
李建琦
2026-08-21 18:30:13 +08:00
commit 6d655c9903
3584 changed files with 1270640 additions and 0 deletions
@@ -0,0 +1,26 @@
import { describe, expect, it } from 'vitest'
import { CONCRETE_PLATFORM_OPTIONS, GROUP_PLATFORM_OPTIONS } from '@/constants/platforms'
const concretePlatforms = [
'anthropic',
'openai',
'gemini',
'antigravity',
'grok',
'kimi',
'zhipu',
'deepseek'
]
describe('platform option catalogs', () => {
it('exposes every concrete account platform', () => {
expect(CONCRETE_PLATFORM_OPTIONS.map((option) => option.value)).toEqual(concretePlatforms)
})
it('adds composite for group-backed filters', () => {
expect(GROUP_PLATFORM_OPTIONS.map((option) => option.value)).toEqual([
...concretePlatforms,
'composite'
])
})
})
+63
View File
@@ -0,0 +1,63 @@
/** WebSearch emulation mode values (must match backend WebSearchMode* constants in account.go) */
export const WEB_SEARCH_MODE_DEFAULT = 'default' as const
export const WEB_SEARCH_MODE_ENABLED = 'enabled' as const
export const WEB_SEARCH_MODE_DISABLED = 'disabled' as const
export type WebSearchMode = typeof WEB_SEARCH_MODE_DEFAULT | typeof WEB_SEARCH_MODE_ENABLED | typeof WEB_SEARCH_MODE_DISABLED
/** Quota notification threshold type values (must match thresholdType* constants in balance_notify_service.go) */
export const QUOTA_THRESHOLD_TYPE_FIXED = 'fixed' as const
export const QUOTA_THRESHOLD_TYPE_PERCENTAGE = 'percentage' as const
export type QuotaThresholdType = typeof QUOTA_THRESHOLD_TYPE_FIXED | typeof QUOTA_THRESHOLD_TYPE_PERCENTAGE
/** Quota reset mode values */
export const QUOTA_RESET_MODE_ROLLING = 'rolling' as const
export const QUOTA_RESET_MODE_FIXED = 'fixed' as const
export type QuotaResetMode = typeof QUOTA_RESET_MODE_ROLLING | typeof QUOTA_RESET_MODE_FIXED
/** Vertex AI location options for Service Account accounts */
export const VERTEX_LOCATION_OPTIONS = [
{
label: 'Common',
options: [
{ value: 'us-central1', label: 'us-central1 (Iowa)' },
{ value: 'global', label: 'global' },
{ value: 'us', label: 'us' },
{ value: 'eu', label: 'eu' }
]
},
{
label: 'United States',
options: [
{ value: 'us-east1', label: 'us-east1 (South Carolina)' },
{ value: 'us-east4', label: 'us-east4 (Northern Virginia)' },
{ value: 'us-east5', label: 'us-east5 (Columbus)' },
{ value: 'us-south1', label: 'us-south1 (Dallas)' },
{ value: 'us-west1', label: 'us-west1 (Oregon)' },
{ value: 'us-west4', label: 'us-west4 (Las Vegas)' }
]
},
{
label: 'Europe',
options: [
{ value: 'europe-west1', label: 'europe-west1 (Belgium)' },
{ value: 'europe-west2', label: 'europe-west2 (London)' },
{ value: 'europe-west3', label: 'europe-west3 (Frankfurt)' },
{ value: 'europe-west4', label: 'europe-west4 (Netherlands)' },
{ value: 'europe-west6', label: 'europe-west6 (Zurich)' },
{ value: 'europe-west8', label: 'europe-west8 (Milan)' },
{ value: 'europe-west9', label: 'europe-west9 (Paris)' }
]
},
{
label: 'Asia Pacific',
options: [
{ value: 'asia-east1', label: 'asia-east1 (Taiwan)' },
{ value: 'asia-east2', label: 'asia-east2 (Hong Kong)' },
{ value: 'asia-northeast1', label: 'asia-northeast1 (Tokyo)' },
{ value: 'asia-northeast3', label: 'asia-northeast3 (Seoul)' },
{ value: 'asia-south1', label: 'asia-south1 (Mumbai)' },
{ value: 'asia-southeast1', label: 'asia-southeast1 (Singapore)' },
{ value: 'australia-southeast1', label: 'australia-southeast1 (Sydney)' }
]
}
] as const
+26
View File
@@ -0,0 +1,26 @@
/** Channel status values (must match service.Status* constants in Go). */
export const CHANNEL_STATUS_ACTIVE = 'active' as const
export const CHANNEL_STATUS_DISABLED = 'disabled' as const
export type ChannelStatus = typeof CHANNEL_STATUS_ACTIVE | typeof CHANNEL_STATUS_DISABLED
/** Billing mode values (must match service.BillingMode* constants in Go). */
export const BILLING_MODE_TOKEN = 'token' as const
export const BILLING_MODE_PER_REQUEST = 'per_request' as const
export const BILLING_MODE_IMAGE = 'image' as const
export const BILLING_MODE_VIDEO = 'video' as const
export type BillingMode =
| typeof BILLING_MODE_TOKEN
| typeof BILLING_MODE_PER_REQUEST
| typeof BILLING_MODE_IMAGE
| typeof BILLING_MODE_VIDEO
/** Billing-model-source values (must match service.BillingModelSource* constants in Go). */
export const BILLING_MODEL_SOURCE_REQUESTED = 'requested' as const
export const BILLING_MODEL_SOURCE_UPSTREAM = 'upstream' as const
export const BILLING_MODEL_SOURCE_CHANNEL_MAPPED = 'channel_mapped' as const
export const BILLING_MODEL_SOURCE_RESPONSE = 'response_model' as const
export type BillingModelSource =
| typeof BILLING_MODEL_SOURCE_REQUESTED
| typeof BILLING_MODEL_SOURCE_UPSTREAM
| typeof BILLING_MODEL_SOURCE_CHANNEL_MAPPED
| typeof BILLING_MODEL_SOURCE_RESPONSE
+74
View File
@@ -0,0 +1,74 @@
/**
* Channel monitor shared constants.
*
* Single source of truth for provider/status string values used by both the
* admin (`views/admin/ChannelMonitorView.vue`) and user-facing
* (`views/user/ChannelStatusView.vue`) screens, plus the shared composable
* `useChannelMonitorFormat`.
*/
import type { APIMode, CheckMode, Provider, MonitorStatus } from '@/api/admin/channelMonitor'
export const PROVIDER_OPENAI: Provider = 'openai'
export const PROVIDER_ANTHROPIC: Provider = 'anthropic'
export const PROVIDER_GEMINI: Provider = 'gemini'
export const PROVIDER_GROK: Provider = 'grok'
export const PROVIDER_ANTIGRAVITY: Provider = 'antigravity'
export const PROVIDER_KIMI: Provider = 'kimi'
export const PROVIDER_ZHIPU: Provider = 'zhipu'
export const PROVIDER_DEEPSEEK: Provider = 'deepseek'
export const DEFAULT_GROK_ENDPOINT = 'https://api.x.ai'
export const DEFAULT_GROK_MODEL = 'grok-4.5'
/** 国产 provider 的官方 endpoint(探活模式预填;配额模式可留空)。 */
export const DEFAULT_KIMI_ENDPOINT = 'https://api.moonshot.cn'
export const DEFAULT_ZHIPU_ENDPOINT = 'https://open.bigmodel.cn'
export const DEFAULT_DEEPSEEK_ENDPOINT = 'https://api.deepseek.com'
export const CHECK_MODE_PROBE: CheckMode = 'probe'
export const CHECK_MODE_QUOTA: CheckMode = 'quota'
export const CHECK_MODE_QUOTA_PROBE: CheckMode = 'quota_probe'
export const API_MODE_CHAT_COMPLETIONS: APIMode = 'chat_completions'
export const API_MODE_RESPONSES: APIMode = 'responses'
export const PROVIDERS: readonly Provider[] = [
PROVIDER_OPENAI,
PROVIDER_ANTHROPIC,
PROVIDER_GEMINI,
PROVIDER_GROK,
PROVIDER_ANTIGRAVITY,
PROVIDER_KIMI,
PROVIDER_ZHIPU,
PROVIDER_DEEPSEEK,
]
/** 仅支持配额模式(无探活 adapter)的 provider。 */
export const QUOTA_ONLY_PROVIDERS: readonly Provider[] = [PROVIDER_ANTIGRAVITY]
export const CHECK_MODES: readonly CheckMode[] = [
CHECK_MODE_PROBE,
CHECK_MODE_QUOTA,
CHECK_MODE_QUOTA_PROBE,
]
export const API_MODES: readonly APIMode[] = [
API_MODE_CHAT_COMPLETIONS,
API_MODE_RESPONSES,
]
export const STATUS_OPERATIONAL: MonitorStatus = 'operational'
export const STATUS_DEGRADED: MonitorStatus = 'degraded'
export const STATUS_FAILED: MonitorStatus = 'failed'
export const STATUS_ERROR: MonitorStatus = 'error'
export const MONITOR_STATUSES: readonly MonitorStatus[] = [
STATUS_OPERATIONAL,
STATUS_DEGRADED,
STATUS_FAILED,
STATUS_ERROR,
]
/** Default polling interval (seconds) for new monitors. */
export const DEFAULT_INTERVAL_SECONDS = 60
+28
View File
@@ -0,0 +1,28 @@
import type { AccountPlatform, GroupPlatform } from '@/types'
export interface PlatformOption<T extends string = string> {
value: T
label: string
}
/**
* Concrete upstream platforms supported by accounts and request routing.
* Keep platform selectors derived from this catalog so newly added providers
* do not silently disappear from list filters.
*/
export const CONCRETE_PLATFORM_OPTIONS = [
{ value: 'anthropic', label: 'Anthropic' },
{ value: 'openai', label: 'OpenAI' },
{ value: 'gemini', label: 'Gemini' },
{ value: 'antigravity', label: 'Antigravity' },
{ value: 'grok', label: 'Grok' },
{ value: 'kimi', label: 'Kimi' },
{ value: 'zhipu', label: 'Zhipu GLM' },
{ value: 'deepseek', label: 'DeepSeek' }
] as const satisfies readonly PlatformOption<AccountPlatform>[]
/** Platforms that can own a group. */
export const GROUP_PLATFORM_OPTIONS = [
...CONCRETE_PLATFORM_OPTIONS,
{ value: 'composite', label: 'Composite' }
] as const satisfies readonly PlatformOption<GroupPlatform>[]