feat(vertex-ai): 重构 Vertex AI 为插件化 adapter,支持 service_account 认证与动态路由

将 Vertex AI 从 transport.py 的硬编码逻辑重构为独立的 plugin adapter,
支持 service_account/oauth 认证类型、模型格式自动识别、区域路由和 URL 构建。
前端新增 Key 认证类型选择和 Service Account 配置表单。

Co-authored-by: NyaDoo <65238336+NyaDoo@users.noreply.github.com>
Closes #194
This commit is contained in:
fawney19
2026-03-01 23:32:48 +08:00
parent a137601728
commit 4bf3a453e7
42 changed files with 1855 additions and 546 deletions

View File

@@ -1550,19 +1550,19 @@ class ProviderAPIKey(ExportMixin, Base):
# 认证类型
# - "api_key": 标准 API Key 认证(默认)
# - "vertex_ai": Google Vertex AI 认证(Service Account JSON
# - 未来可扩展oauth2, azure_ad, aws_iam 等
# - "service_account": GCP Service Account JSON 认证
# - "oauth": OAuth access_token / refresh_token 认证
auth_type = Column(String(20), default="api_key", nullable=False)
# API密钥加密存储
# - auth_type="api_key" 时:存储 API Key 字符串
# - auth_type="vertex_ai" :可为,敏感凭证存在 auth_config 中
# - auth_type="service_account"/"oauth" :可为占位符,敏感凭证存在 auth_config 中
api_key = Column(Text, nullable=False) # 使用 Text 支持加密后的 OAuth token
# 认证配置(加密存储)
# - auth_type="api_key" 时:可为空
# - auth_type="vertex_ai" 时:存储加密后的 Service Account JSON
# - auth_type="oauth2" 时:存储加密后的 {client_id, client_secret, token_url, scope}
# - auth_type="service_account" 时:存储加密后的 Service Account JSON
# - auth_type="oauth" 时:存储加密后的 {refresh_token, expires_at, ...}
auth_config = Column(Text, nullable=True)
name = Column(String(100), nullable=False) # 密钥名称(必填,用于识别)
note = Column(String(500), nullable=True) # 备注说明(可选)

View File

@@ -261,7 +261,7 @@ class ProviderEndpointCreate(BaseModel):
api_format: str = Field(
...,
description=(
"Endpoint signature例如: claude:chat/claude:cli, openai:chat/openai:cli/openai:video, gemini:chat/gemini:cli/gemini:video"
"Endpoint signature例如: claude:chat/claude:cli, openai:chat/openai:cli/openai:compact/openai:video, gemini:chat/gemini:cli/gemini:video"
),
)
base_url: str = Field(..., min_length=1, max_length=500, description="API 基础 URL")
@@ -435,14 +435,14 @@ class EndpointAPIKeyCreate(BaseModel):
api_key: str = Field(
default="", max_length=10000, description="API Key标准认证时必填将自动加密"
)
auth_type: Literal["api_key", "vertex_ai", "oauth"] = Field(
auth_type: Literal["api_key", "service_account", "oauth"] = Field(
default="api_key",
description="认证类型api_key标准 API Key/ vertex_aiVertex AI Service Account/ oauthOAuth access_token",
description="认证类型api_key标准 API Key/ service_accountGCP Service Account/ oauthOAuth access_token",
)
auth_config: dict[str, Any] | None = Field(
default=None,
description=(
"认证配置JSONvertex_ai 时存储完整 Service Account JSON"
"认证配置JSONservice_account 时存储完整 Service Account JSON"
"oauth 时存储 token/refresh/expires_at 等(后端加密存储,不在响应中返回)"
),
)
@@ -590,14 +590,14 @@ class EndpointAPIKeyUpdate(BaseModel):
max_length=10000,
description="API Key标准认证时使用将自动加密",
)
auth_type: Literal["api_key", "vertex_ai", "oauth"] | None = Field(
auth_type: Literal["api_key", "service_account", "oauth"] | None = Field(
default=None,
description="认证类型api_key标准 API Key/ vertex_aiVertex AI Service Account/ oauthOAuth access_token",
description="认证类型api_key标准 API Key/ service_accountGCP Service Account/ oauthOAuth access_token",
)
auth_config: dict[str, Any] | None = Field(
default=None,
description=(
"认证配置JSONvertex_ai 时存储完整 Service Account JSON"
"认证配置JSONservice_account 时存储完整 Service Account JSON"
"oauth 时存储 token/refresh/expires_at 等(后端加密存储,不在响应中返回)"
),
)
@@ -719,7 +719,9 @@ class EndpointAPIKeyResponse(BaseModel):
# Key 信息(脱敏)
api_key_masked: str = Field(..., description="脱敏后的 Key")
api_key_plain: str | None = Field(default=None, description="完整的 Key")
auth_type: str = Field(default="api_key", description="认证类型api_key 或 vertex_ai")
auth_type: str = Field(
default="api_key", description="认证类型api_key / service_account / oauth"
)
# auth_config 不在响应中返回(包含敏感信息),前端通过 auth_type 判断类型
name: str = Field(..., description="密钥名称")