coding-proxy 0.1.0__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- coding/__init__.py +0 -0
- coding/proxy/__init__.py +3 -0
- coding/proxy/__main__.py +5 -0
- coding/proxy/auth/__init__.py +13 -0
- coding/proxy/auth/providers/__init__.py +6 -0
- coding/proxy/auth/providers/base.py +35 -0
- coding/proxy/auth/providers/github.py +133 -0
- coding/proxy/auth/providers/google.py +237 -0
- coding/proxy/auth/runtime.py +122 -0
- coding/proxy/auth/store.py +74 -0
- coding/proxy/cli/__init__.py +151 -0
- coding/proxy/cli/auth_commands.py +224 -0
- coding/proxy/compat/__init__.py +30 -0
- coding/proxy/compat/canonical.py +193 -0
- coding/proxy/compat/session_store.py +137 -0
- coding/proxy/config/__init__.py +6 -0
- coding/proxy/config/auth_schema.py +24 -0
- coding/proxy/config/loader.py +139 -0
- coding/proxy/config/resiliency.py +46 -0
- coding/proxy/config/routing.py +279 -0
- coding/proxy/config/schema.py +280 -0
- coding/proxy/config/server.py +23 -0
- coding/proxy/config/vendors.py +53 -0
- coding/proxy/convert/__init__.py +14 -0
- coding/proxy/convert/anthropic_to_gemini.py +352 -0
- coding/proxy/convert/anthropic_to_openai.py +352 -0
- coding/proxy/convert/gemini_sse_adapter.py +169 -0
- coding/proxy/convert/gemini_to_anthropic.py +98 -0
- coding/proxy/convert/openai_to_anthropic.py +88 -0
- coding/proxy/logging/__init__.py +49 -0
- coding/proxy/logging/db.py +308 -0
- coding/proxy/logging/stats.py +129 -0
- coding/proxy/model/__init__.py +93 -0
- coding/proxy/model/auth.py +32 -0
- coding/proxy/model/compat.py +153 -0
- coding/proxy/model/constants.py +21 -0
- coding/proxy/model/pricing.py +70 -0
- coding/proxy/model/token.py +64 -0
- coding/proxy/model/vendor.py +218 -0
- coding/proxy/pricing.py +100 -0
- coding/proxy/routing/__init__.py +47 -0
- coding/proxy/routing/circuit_breaker.py +152 -0
- coding/proxy/routing/error_classifier.py +67 -0
- coding/proxy/routing/executor.py +453 -0
- coding/proxy/routing/model_mapper.py +90 -0
- coding/proxy/routing/quota_guard.py +169 -0
- coding/proxy/routing/rate_limit.py +159 -0
- coding/proxy/routing/retry.py +82 -0
- coding/proxy/routing/router.py +84 -0
- coding/proxy/routing/session_manager.py +62 -0
- coding/proxy/routing/tier.py +171 -0
- coding/proxy/routing/usage_parser.py +193 -0
- coding/proxy/routing/usage_recorder.py +131 -0
- coding/proxy/server/__init__.py +1 -0
- coding/proxy/server/app.py +142 -0
- coding/proxy/server/factory.py +175 -0
- coding/proxy/server/request_normalizer.py +139 -0
- coding/proxy/server/responses.py +74 -0
- coding/proxy/server/routes.py +264 -0
- coding/proxy/streaming/__init__.py +1 -0
- coding/proxy/streaming/anthropic_compat.py +484 -0
- coding/proxy/vendors/__init__.py +29 -0
- coding/proxy/vendors/anthropic.py +44 -0
- coding/proxy/vendors/antigravity.py +328 -0
- coding/proxy/vendors/base.py +353 -0
- coding/proxy/vendors/copilot.py +702 -0
- coding/proxy/vendors/copilot_models.py +438 -0
- coding/proxy/vendors/copilot_token_manager.py +167 -0
- coding/proxy/vendors/copilot_urls.py +16 -0
- coding/proxy/vendors/mixins.py +71 -0
- coding/proxy/vendors/token_manager.py +128 -0
- coding/proxy/vendors/zhipu.py +243 -0
- coding_proxy-0.1.0.dist-info/METADATA +184 -0
- coding_proxy-0.1.0.dist-info/RECORD +77 -0
- coding_proxy-0.1.0.dist-info/WHEEL +4 -0
- coding_proxy-0.1.0.dist-info/entry_points.txt +2 -0
- coding_proxy-0.1.0.dist-info/licenses/LICENSE +201 -0
|
@@ -0,0 +1,280 @@
|
|
|
1
|
+
"""Pydantic 配置模型 — 聚合层(re-export 所有子模块符号).
|
|
2
|
+
|
|
3
|
+
本文件为向后兼容的聚合入口点,所有配置模型已正交拆分至以下子模块:
|
|
4
|
+
|
|
5
|
+
- :mod:`.server` – ServerConfig / DatabaseConfig / LoggingConfig
|
|
6
|
+
- :mod:`.vendors` – AnthropicConfig / CopilotConfig / AntigravityConfig / ZhipuConfig
|
|
7
|
+
- :mod:`.resiliency` – CircuitBreakerConfig / RetryConfig / FailoverConfig / QuotaGuardConfig
|
|
8
|
+
- :mod:`.routing` – VendorType / VendorConfig / ModelMappingRule / ModelPricingEntry
|
|
9
|
+
- :mod:`.auth_schema` – AuthConfig
|
|
10
|
+
|
|
11
|
+
:py:class:`ProxyConfig` 及其旧格式迁移逻辑保留在此文件中。
|
|
12
|
+
"""
|
|
13
|
+
|
|
14
|
+
from __future__ import annotations
|
|
15
|
+
|
|
16
|
+
import logging
|
|
17
|
+
from pathlib import Path
|
|
18
|
+
from typing import Any
|
|
19
|
+
|
|
20
|
+
from pydantic import BaseModel, Field, model_validator
|
|
21
|
+
|
|
22
|
+
# ── 子模块 re-export ────────────────────────────────────────────
|
|
23
|
+
|
|
24
|
+
from .server import ServerConfig, DatabaseConfig, LoggingConfig # noqa: F401
|
|
25
|
+
from .vendors import ( # noqa: F401
|
|
26
|
+
AnthropicConfig,
|
|
27
|
+
CopilotConfig,
|
|
28
|
+
AntigravityConfig,
|
|
29
|
+
ZhipuConfig,
|
|
30
|
+
)
|
|
31
|
+
from .resiliency import ( # noqa: F401
|
|
32
|
+
CircuitBreakerConfig,
|
|
33
|
+
RetryConfig,
|
|
34
|
+
FailoverConfig,
|
|
35
|
+
QuotaGuardConfig,
|
|
36
|
+
)
|
|
37
|
+
from .routing import ( # noqa: F401
|
|
38
|
+
VendorType,
|
|
39
|
+
VendorConfig,
|
|
40
|
+
TierConfig, # 向后兼容别名
|
|
41
|
+
BackendType, # 向后兼容别名
|
|
42
|
+
ModelMappingRule,
|
|
43
|
+
ModelPricingEntry,
|
|
44
|
+
_COPILOT_FIELDS,
|
|
45
|
+
_ANTIGRAVITY_FIELDS,
|
|
46
|
+
_ZHIPU_FIELDS,
|
|
47
|
+
_VENDOR_EXCLUSIVE_FIELDS,
|
|
48
|
+
_BACKEND_EXCLUSIVE_FIELDS, # 向后兼容别名
|
|
49
|
+
)
|
|
50
|
+
from .auth_schema import AuthConfig # noqa: F401
|
|
51
|
+
|
|
52
|
+
logger = logging.getLogger(__name__)
|
|
53
|
+
|
|
54
|
+
|
|
55
|
+
class ProxyConfig(BaseModel):
|
|
56
|
+
"""顶层配置模型.
|
|
57
|
+
|
|
58
|
+
.. note::
|
|
59
|
+
以下字段为 **旧 flat 格式**(已废弃,保留仅用于向后兼容迁移):
|
|
60
|
+
``primary``, ``copilot``, ``antigravity``, ``fallback``,
|
|
61
|
+
``circuit_breaker``, ``copilot_circuit_breaker``, ``antigravity_circuit_breaker``,
|
|
62
|
+
``quota_guard``, ``copilot_quota_guard``, ``antigravity_quota_guard``
|
|
63
|
+
|
|
64
|
+
新配置应使用 ``vendors`` 列表格式(参见 config.example.yaml)。
|
|
65
|
+
旧格式会在 ``_migrate_legacy_fields`` 中自动转换为 vendors。
|
|
66
|
+
"""
|
|
67
|
+
|
|
68
|
+
server: ServerConfig = ServerConfig()
|
|
69
|
+
|
|
70
|
+
# ── Legacy 字段(旧 flat 格式,由 _migrate_legacy_fields 自动迁移至 vendors) ──
|
|
71
|
+
primary: AnthropicConfig = Field(
|
|
72
|
+
default=AnthropicConfig(),
|
|
73
|
+
description="[legacy] Anthropic 主供应商配置;新格式请使用 vendors[].vendor=anthropic",
|
|
74
|
+
)
|
|
75
|
+
copilot: CopilotConfig = Field(
|
|
76
|
+
default=CopilotConfig(),
|
|
77
|
+
description="[legacy] Copilot 供应商配置;新格式请使用 vendors[].vendor=copilot",
|
|
78
|
+
)
|
|
79
|
+
antigravity: AntigravityConfig = Field(
|
|
80
|
+
default=AntigravityConfig(),
|
|
81
|
+
description="[legacy] Antigravity 供应商配置;新格式请使用 vendors[].vendor=antigravity",
|
|
82
|
+
)
|
|
83
|
+
fallback: ZhipuConfig = Field(
|
|
84
|
+
default=ZhipuConfig(),
|
|
85
|
+
description="[legacy] 智谱兜底供应商配置;新格式请使用 vendors[].vendor=zhipu",
|
|
86
|
+
)
|
|
87
|
+
circuit_breaker: CircuitBreakerConfig = Field(
|
|
88
|
+
default=CircuitBreakerConfig(),
|
|
89
|
+
description="[legacy] 全局熔断器配置;新格式请使用 vendors[].circuit_breaker",
|
|
90
|
+
)
|
|
91
|
+
copilot_circuit_breaker: CircuitBreakerConfig = Field(
|
|
92
|
+
default=CircuitBreakerConfig(),
|
|
93
|
+
description="[legacy] Copilot 熔断器配置;新格式请使用 vendors[vendor=copilot].circuit_breaker",
|
|
94
|
+
)
|
|
95
|
+
antigravity_circuit_breaker: CircuitBreakerConfig = Field(
|
|
96
|
+
default=CircuitBreakerConfig(),
|
|
97
|
+
description="[legacy] Antigravity 熔断器配置;新格式请使用 vendors[vendor=antigravity].circuit_breaker",
|
|
98
|
+
)
|
|
99
|
+
failover: FailoverConfig = FailoverConfig()
|
|
100
|
+
model_mapping: list[ModelMappingRule] = Field(
|
|
101
|
+
default=[
|
|
102
|
+
ModelMappingRule(pattern="claude-sonnet-.*", target="glm-5.1", is_regex=True),
|
|
103
|
+
ModelMappingRule(pattern="claude-opus-.*", target="glm-5.1", is_regex=True),
|
|
104
|
+
ModelMappingRule(pattern="claude-haiku-.*", target="glm-4.5-air", is_regex=True),
|
|
105
|
+
ModelMappingRule(pattern="claude-.*", target="glm-5.1", is_regex=True),
|
|
106
|
+
],
|
|
107
|
+
)
|
|
108
|
+
quota_guard: QuotaGuardConfig = Field(
|
|
109
|
+
default=QuotaGuardConfig(),
|
|
110
|
+
description="[legacy] 全局配额守卫;新格式请使用 vendors[].quota_guard",
|
|
111
|
+
)
|
|
112
|
+
copilot_quota_guard: QuotaGuardConfig = Field(
|
|
113
|
+
default=QuotaGuardConfig(),
|
|
114
|
+
description="[legacy] Copilot 配额守卫;新格式请使用 vendors[vendor=copilot].quota_guard",
|
|
115
|
+
)
|
|
116
|
+
antigravity_quota_guard: QuotaGuardConfig = Field(
|
|
117
|
+
default=QuotaGuardConfig(),
|
|
118
|
+
description="[legacy] Antigravity 配额守卫;新格式请使用 vendors[vendor=antigravity].quota_guard",
|
|
119
|
+
)
|
|
120
|
+
auth: AuthConfig = AuthConfig()
|
|
121
|
+
database: DatabaseConfig = DatabaseConfig()
|
|
122
|
+
logging: LoggingConfig = LoggingConfig()
|
|
123
|
+
# 模型定价(USD / 1M tokens),按 (vendor, model) 匹配
|
|
124
|
+
pricing: list[ModelPricingEntry] = Field(default_factory=list)
|
|
125
|
+
# 新格式:vendors 列表(供应商定义)
|
|
126
|
+
vendors: list[VendorConfig] = Field(default_factory=list)
|
|
127
|
+
# 降级链路优先级(可选);None 时回退到 vendors 列表顺序
|
|
128
|
+
tiers: list[VendorType] | None = Field(
|
|
129
|
+
default=None,
|
|
130
|
+
description=(
|
|
131
|
+
"显式指定降级链路的优先级顺序(索引越小优先级越高)。"
|
|
132
|
+
"引用的 vendor 必须在 vendors 中存在且 enabled=True。"
|
|
133
|
+
"未配置时回退到 vendors 列表原始顺序。"
|
|
134
|
+
),
|
|
135
|
+
)
|
|
136
|
+
|
|
137
|
+
@model_validator(mode="before")
|
|
138
|
+
@classmethod
|
|
139
|
+
def _migrate_legacy_fields(cls, data: Any) -> Any:
|
|
140
|
+
"""向后兼容迁移(legacy flat 格式 → vendors 列表格式).
|
|
141
|
+
|
|
142
|
+
迁移规则:
|
|
143
|
+
1. ``anthropic`` / ``zhipu`` 字段名自动映射为 ``primary`` / ``fallback``
|
|
144
|
+
2. 若配置中未显式指定 ``vendors``,则从旧 flat 格式字段自动生成
|
|
145
|
+
"""
|
|
146
|
+
if not isinstance(data, dict):
|
|
147
|
+
return data
|
|
148
|
+
|
|
149
|
+
# 1. 字段别名迁移
|
|
150
|
+
if "anthropic" in data and "primary" not in data:
|
|
151
|
+
data["primary"] = data.pop("anthropic")
|
|
152
|
+
if "zhipu" in data and "fallback" not in data:
|
|
153
|
+
data["fallback"] = data.pop("zhipu")
|
|
154
|
+
|
|
155
|
+
# 2. 若已有 vendors 配置则直接使用,跳过自动迁移
|
|
156
|
+
# 同时支持旧的 tiers 字段名(向后兼容 YAML)
|
|
157
|
+
# 使用 key 存在性检测(而非真值检测),以正确处理 vendors: [] 等显式空配置
|
|
158
|
+
if "vendors" in data or "tiers" in data:
|
|
159
|
+
# 如果用户使用了旧的 tiers 字段名但实际是 vendor 定义列表,重映射
|
|
160
|
+
if "tiers" in data and "vendors" not in data and isinstance(data["tiers"], list):
|
|
161
|
+
# 检测是否为新格式的 vendor 定义列表(每项有 vendor 字段,兼容旧 backend 字段)
|
|
162
|
+
first_item = data["tiers"][0] if data["tiers"] else {}
|
|
163
|
+
if isinstance(first_item, dict) and ("vendor" in first_item or "backend" in first_item):
|
|
164
|
+
data["vendors"] = data.pop("tiers")
|
|
165
|
+
return data
|
|
166
|
+
|
|
167
|
+
# 3. 从旧 flat 格式自动构建 vendors(触发时记录废弃日志)
|
|
168
|
+
vendors: list[dict[str, Any]] = []
|
|
169
|
+
_legacy_keys = {"primary", "copilot", "antigravity", "fallback",
|
|
170
|
+
"circuit_breaker", "copilot_circuit_breaker", "antigravity_circuit_breaker",
|
|
171
|
+
"quota_guard", "copilot_quota_guard", "antigravity_quota_guard"}
|
|
172
|
+
if any(k in data for k in _legacy_keys):
|
|
173
|
+
logger.info(
|
|
174
|
+
"检测到旧 flat 格式配置字段,已自动迁移至 vendors 列表格式。"
|
|
175
|
+
"建议迁移至 config.example.yaml 中的 vendors 新格式。",
|
|
176
|
+
)
|
|
177
|
+
|
|
178
|
+
primary = data.get("primary") or {}
|
|
179
|
+
if primary.get("enabled", True):
|
|
180
|
+
vendor_cfg: dict[str, Any] = {"vendor": "anthropic", **primary}
|
|
181
|
+
cb = data.get("circuit_breaker")
|
|
182
|
+
if cb:
|
|
183
|
+
vendor_cfg["circuit_breaker"] = cb
|
|
184
|
+
qg = data.get("quota_guard")
|
|
185
|
+
if qg:
|
|
186
|
+
vendor_cfg["quota_guard"] = qg
|
|
187
|
+
vendors.append(vendor_cfg)
|
|
188
|
+
|
|
189
|
+
copilot = data.get("copilot") or {}
|
|
190
|
+
if copilot.get("enabled", False):
|
|
191
|
+
vendor_cfg = {"vendor": "copilot", **copilot}
|
|
192
|
+
cb = data.get("copilot_circuit_breaker")
|
|
193
|
+
if cb:
|
|
194
|
+
vendor_cfg["circuit_breaker"] = cb
|
|
195
|
+
qg = data.get("copilot_quota_guard")
|
|
196
|
+
if qg:
|
|
197
|
+
vendor_cfg["quota_guard"] = qg
|
|
198
|
+
vendors.append(vendor_cfg)
|
|
199
|
+
|
|
200
|
+
antigravity = data.get("antigravity") or {}
|
|
201
|
+
if antigravity.get("enabled", False):
|
|
202
|
+
vendor_cfg = {"vendor": "antigravity", **antigravity}
|
|
203
|
+
cb = data.get("antigravity_circuit_breaker")
|
|
204
|
+
if cb:
|
|
205
|
+
vendor_cfg["circuit_breaker"] = cb
|
|
206
|
+
qg = data.get("antigravity_quota_guard")
|
|
207
|
+
if qg:
|
|
208
|
+
vendor_cfg["quota_guard"] = qg
|
|
209
|
+
vendors.append(vendor_cfg)
|
|
210
|
+
|
|
211
|
+
fallback = data.get("fallback") or {}
|
|
212
|
+
if fallback.get("enabled", True):
|
|
213
|
+
# 终端层:不设置 circuit_breaker
|
|
214
|
+
vendors.append({"vendor": "zhipu", **fallback})
|
|
215
|
+
|
|
216
|
+
data["vendors"] = vendors
|
|
217
|
+
return data
|
|
218
|
+
|
|
219
|
+
@model_validator(mode="after")
|
|
220
|
+
def _validate_tiers(self) -> "ProxyConfig":
|
|
221
|
+
"""校验 tiers 引用的 vendor 必须在 enabled vendors 中存在."""
|
|
222
|
+
if self.tiers is None:
|
|
223
|
+
return self # 未配置,跳过校验
|
|
224
|
+
|
|
225
|
+
# 构建 enabled vendor 的 name 集合
|
|
226
|
+
enabled_vendors = {v.vendor for v in self.vendors if v.enabled}
|
|
227
|
+
|
|
228
|
+
# 检查重复
|
|
229
|
+
seen: set[str] = set()
|
|
230
|
+
for name in self.tiers:
|
|
231
|
+
if name in seen:
|
|
232
|
+
raise ValueError(
|
|
233
|
+
f"tiers 包含重复的 vendor 名称: {name!r}"
|
|
234
|
+
)
|
|
235
|
+
seen.add(name)
|
|
236
|
+
|
|
237
|
+
# 检查引用是否存在
|
|
238
|
+
all_vendors = {v.vendor for v in self.vendors}
|
|
239
|
+
if name not in all_vendors:
|
|
240
|
+
raise ValueError(
|
|
241
|
+
f"tiers 引用了不存在的 vendor: {name!r}。"
|
|
242
|
+
f"可用的 vendor: {sorted(all_vendors)}"
|
|
243
|
+
)
|
|
244
|
+
|
|
245
|
+
# 存在但 disabled → warning
|
|
246
|
+
if name not in enabled_vendors:
|
|
247
|
+
logger.warning(
|
|
248
|
+
"tiers 引用了 disabled 的 vendor: %s,"
|
|
249
|
+
"该层级将在运行时被跳过",
|
|
250
|
+
name,
|
|
251
|
+
)
|
|
252
|
+
|
|
253
|
+
return self
|
|
254
|
+
|
|
255
|
+
@property
|
|
256
|
+
def db_path(self) -> Path:
|
|
257
|
+
return Path(self.database.path).expanduser()
|
|
258
|
+
|
|
259
|
+
@property
|
|
260
|
+
def compat_state_path(self) -> Path:
|
|
261
|
+
return Path(self.database.compat_state_path).expanduser()
|
|
262
|
+
|
|
263
|
+
|
|
264
|
+
__all__ = [
|
|
265
|
+
"ProxyConfig",
|
|
266
|
+
# server
|
|
267
|
+
"ServerConfig", "DatabaseConfig", "LoggingConfig",
|
|
268
|
+
# vendors
|
|
269
|
+
"AnthropicConfig", "CopilotConfig", "AntigravityConfig", "ZhipuConfig",
|
|
270
|
+
# resiliency
|
|
271
|
+
"CircuitBreakerConfig", "RetryConfig", "FailoverConfig", "QuotaGuardConfig",
|
|
272
|
+
# routing
|
|
273
|
+
"VendorType", "VendorConfig", "ModelMappingRule", "ModelPricingEntry",
|
|
274
|
+
"TierConfig", # 向后兼容别名
|
|
275
|
+
"BackendType", # 向后兼容别名
|
|
276
|
+
"_COPILOT_FIELDS", "_ANTIGRAVITY_FIELDS", "_ZHIPU_FIELDS",
|
|
277
|
+
"_VENDOR_EXCLUSIVE_FIELDS", "_BACKEND_EXCLUSIVE_FIELDS",
|
|
278
|
+
# auth
|
|
279
|
+
"AuthConfig",
|
|
280
|
+
]
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
"""基础设施配置模型."""
|
|
2
|
+
|
|
3
|
+
from __future__ import annotations
|
|
4
|
+
|
|
5
|
+
from pydantic import BaseModel
|
|
6
|
+
|
|
7
|
+
|
|
8
|
+
class ServerConfig(BaseModel):
|
|
9
|
+
host: str = "127.0.0.1"
|
|
10
|
+
port: int = 8046
|
|
11
|
+
|
|
12
|
+
|
|
13
|
+
class DatabaseConfig(BaseModel):
|
|
14
|
+
path: str = "~/.coding-proxy/usage.db"
|
|
15
|
+
compat_state_path: str = "~/.coding-proxy/compat.db"
|
|
16
|
+
compat_state_ttl_seconds: int = 86400
|
|
17
|
+
|
|
18
|
+
|
|
19
|
+
class LoggingConfig(BaseModel):
|
|
20
|
+
level: str = "INFO"
|
|
21
|
+
file: str | None = None
|
|
22
|
+
|
|
23
|
+
__all__ = ["ServerConfig", "DatabaseConfig", "LoggingConfig"]
|
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
"""供应商专属配置模型."""
|
|
2
|
+
|
|
3
|
+
from __future__ import annotations
|
|
4
|
+
|
|
5
|
+
from pydantic import BaseModel, Field
|
|
6
|
+
|
|
7
|
+
|
|
8
|
+
class AnthropicConfig(BaseModel):
|
|
9
|
+
enabled: bool = True
|
|
10
|
+
base_url: str = "https://api.anthropic.com"
|
|
11
|
+
timeout_ms: int = 300000
|
|
12
|
+
|
|
13
|
+
|
|
14
|
+
class CopilotConfig(BaseModel):
|
|
15
|
+
"""GitHub Copilot 供应商配置."""
|
|
16
|
+
|
|
17
|
+
enabled: bool = False
|
|
18
|
+
github_token: str = ""
|
|
19
|
+
account_type: str = "individual"
|
|
20
|
+
token_url: str = "https://api.github.com/copilot_internal/v2/token"
|
|
21
|
+
base_url: str = ""
|
|
22
|
+
models_cache_ttl_seconds: int = 300
|
|
23
|
+
timeout_ms: int = 300000
|
|
24
|
+
|
|
25
|
+
|
|
26
|
+
class AntigravityConfig(BaseModel):
|
|
27
|
+
"""Google Antigravity Claude 供应商配置."""
|
|
28
|
+
|
|
29
|
+
enabled: bool = False
|
|
30
|
+
client_id: str = ""
|
|
31
|
+
client_secret: str = ""
|
|
32
|
+
refresh_token: str = ""
|
|
33
|
+
base_url: str = "https://generativelanguage.googleapis.com/v1beta"
|
|
34
|
+
model_endpoint: str = "models/claude-sonnet-4-20250514"
|
|
35
|
+
timeout_ms: int = 300000
|
|
36
|
+
safety_settings: dict[str, str] | None = None
|
|
37
|
+
|
|
38
|
+
|
|
39
|
+
class ZhipuConfig(BaseModel):
|
|
40
|
+
"""智谱 GLM 供应商配置(原生 Anthropic 兼容端点).
|
|
41
|
+
|
|
42
|
+
官方端点已完整支持 Anthropic Messages API 协议,
|
|
43
|
+
无需工具截断、thinking 剥离等适配逻辑.
|
|
44
|
+
"""
|
|
45
|
+
|
|
46
|
+
enabled: bool = True
|
|
47
|
+
base_url: str = "https://open.bigmodel.cn/api/anthropic"
|
|
48
|
+
api_key: str = ""
|
|
49
|
+
timeout_ms: int = 3000000
|
|
50
|
+
|
|
51
|
+
__all__ = [
|
|
52
|
+
"AnthropicConfig", "CopilotConfig", "AntigravityConfig", "ZhipuConfig",
|
|
53
|
+
]
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
"""Anthropic ↔ Gemini 格式转换模块."""
|
|
2
|
+
|
|
3
|
+
from .anthropic_to_openai import convert_request as convert_openai_request
|
|
4
|
+
from .anthropic_to_gemini import convert_request
|
|
5
|
+
from .gemini_to_anthropic import convert_response, extract_usage
|
|
6
|
+
from .openai_to_anthropic import convert_response as convert_openai_response
|
|
7
|
+
|
|
8
|
+
__all__ = [
|
|
9
|
+
"convert_request",
|
|
10
|
+
"convert_response",
|
|
11
|
+
"extract_usage",
|
|
12
|
+
"convert_openai_request",
|
|
13
|
+
"convert_openai_response",
|
|
14
|
+
]
|