افزودن ارائه‌دهندهٔ agy (Google Antigravity) با لاگین headless و پول چرخشی اکانت

- Adapter اکانت‌محور با چرخش round-robin و بنچ‌شدن خودکار روی ۴۲۹/۴۰۱
- ورود ادمین از طریق URL بازگشتی گوگل (PKCE) و ذخیرهٔ رمزنگاری‌شدهٔ refresh token
- صفحهٔ مدیریت اکانت‌های agy در پنل ادمین به همراه تست و فعال/غیرفعال‌سازی
- مهاجرت Alembic b1c2d3e4f5a6 برای ستون‌های اکانت agy
- seed همیشه کاتالوگ agy را می‌سازد و فقط با AI_DEFAULT_PROVIDER=agy مسیریابی می‌شود
This commit is contained in:
mjalmoudy94
2026-10-13 08:20:27 +03:30
parent 54074f10c3
commit 3d1e98f4fb
25 changed files with 3073 additions and 10 deletions
@@ -44,13 +44,21 @@ class ModelProviderPort(Protocol):
self,
*,
model: AiModel,
credential: ModelCredential | None,
credential: ModelCredential | None = None,
credentials: list[ModelCredential] | None = None,
messages: list[ChatMessage],
system: str = "",
temperature: float = 0.2,
max_tokens: int = 2048,
) -> ModelResponse:
"""Run one completion. Must raise ``ProviderUnavailableError`` on failure."""
"""Run one completion. Must raise ``ProviderUnavailableError`` on failure.
``credential`` is the single active credential (the only input key-based
providers need). ``credentials`` is the full usable pool: providers whose
accounts rotate (agy) accept it and fan out across the set, keeping one
account's rate limit from becoming everyone's outage; providers without
a pool ignore it.
"""
...
async def health(self) -> ModelHealth:
@@ -714,10 +714,17 @@ class WorkforceService:
) -> str:
"""Run one completion and record its usage. The single model entry point."""
model = await self._resolve_model(employee)
credential = await self.credentials.get_active_for_provider(model.provider_id)
# Pool-aware: rotation providers (agy) fan out across every usable
# account; key-based providers simply get their one active credential.
pool = await self.credentials.list_active_for_provider(model.provider_id)
credential = pool[0] if pool else None
response = await self.provider.complete(
model=model, credential=credential, messages=messages, system=system
model=model,
credential=credential,
credentials=pool or None,
messages=messages,
system=system,
)
await self._record_usage(