Files
smart-org/apps/api/app/infrastructure/adapters/registry.py
T
mjalmoudy94 da5a2a5d1a agy تنها ارائه‌دهندهٔ مدل؛ حذف بخش ارائه‌دهنده‌ها و افزودن زنجیرهٔ انتخاب مدل
- حذف کامل providerهای mock و openai_compatible: دامنه، آداپوترها، رجیستری، کانفیگ، seed و رابطٔ مدیریت
- بخش «ارائه‌دهنده‌ها» از کنسول حذف شد؛ ورود اکانت‌ها فقط از صفحهٔ اکانت‌های agy
- صفحهٔ مدل‌ها بازطراحی شد: ارائه‌دهنده → اکانت → مدل (کاتالوگ لحظه‌ای و زندهٔ همان اکانت از Google) → افورت استدلال؛ بدون هیچ ورود دستی نام مدل
- مدل‌ها ستون reasoning_effort گرفتند؛ آداپتور آن را به thinkingConfig (بودجهٔ ۱۰۲۴ تا ۳۲۷۶۸) ترجمه می‌کند و فقط به مدل‌های استدلالی می‌فرستد
- مهاجرت c2d3e4f5b6a7: افزودن reasoning_effort و حذف ردیف‌های providerهای قدیمی
- تست‌ها: ۲۴۶ تست بک‌اند و ۵۱ تست فرانت سبز؛ ruff و mypy و tsc و eslint تمیز
2026-10-13 10:01:11 +03:30

151 lines
4.8 KiB
Python

"""Adapter registry.
One place decides which concrete adapter backs each port, driven purely by the
``*_PROVIDER`` environment switches. Everything defaults to ``mock`` so a fresh
clone runs with no credentials — *except* the model provider: ``agy`` (Google
Antigravity) is the only one the platform talks to, and its accounts are added
from the admin console.
Adapters that hold process state (the mock Git forge, the mock port ledger) are
cached as singletons so behaviour is consistent within a process.
"""
from __future__ import annotations
import logging
from functools import lru_cache
from app.core.config import settings
from app.core.errors import ProviderUnavailableError
from app.infrastructure.adapters import mock
logger = logging.getLogger("agy.registry")
@lru_cache
def get_model_provider():
"""The one model adapter: agy over its logged-in account pool."""
configured = settings.ai_default_provider.strip().lower()
if configured != "agy":
# Tolerate a stale ``AI_DEFAULT_PROVIDER`` from before agy became the
# only provider: warn loudly, keep serving with agy either way.
logger.warning(
"AI_DEFAULT_PROVIDER=%r is obsolete — agy is the only supported "
"model provider; using it",
settings.ai_default_provider,
)
from app.infrastructure.adapters.agy import (
AgyModelAdapter,
load_agy_accounts,
report_agy_state,
)
return AgyModelAdapter(loader=load_agy_accounts, report=report_agy_state)
@lru_cache
def get_git_provider():
provider = settings.git_provider.lower()
if provider == "mock":
return mock.MockGitAdapter()
if provider == "gitea":
from app.infrastructure.adapters.gitea import GiteaGitAdapter
return GiteaGitAdapter(
base_url=settings.gitea_internal_url or settings.gitea_url,
admin_user=settings.gitea_admin_user,
admin_token=settings.gitea_admin_token,
)
raise ProviderUnavailableError(
f"GIT_PROVIDER='{provider}' پشتیبانی نمی‌شود. مقادیر مجاز: mock | gitea"
)
@lru_cache
def get_domain_router():
provider = settings.domain_router.lower()
if provider == "mock":
return mock.MockDomainRouterAdapter(
root_domain=settings.preview_root_domain,
port_start=settings.preview_port_start,
port_end=settings.preview_port_end,
)
if provider == "caddy":
from app.infrastructure.adapters.caddy import CaddyDomainRouterAdapter
return CaddyDomainRouterAdapter(
caddyfile_path=settings.caddyfile_path,
root_domain=settings.preview_root_domain,
port_start=settings.preview_port_start,
port_end=settings.preview_port_end,
)
raise ProviderUnavailableError(
f"DOMAIN_ROUTER='{provider}' پشتیبانی نمی‌شود. مقادیر مجاز: mock | caddy"
)
@lru_cache
def get_sandbox_provider():
provider = settings.sandbox_provider.lower()
if provider == "mock":
return mock.LocalMockSandboxAdapter(max_output_bytes=settings.sandbox_max_output_bytes)
if provider in {"daytona", "e2b"}:
from app.infrastructure.adapters.sandbox_remote import build_remote_sandbox_adapter
return build_remote_sandbox_adapter(
provider,
daytona_api_key=settings.daytona_api_key,
daytona_api_url=settings.daytona_api_url,
e2b_api_key=settings.e2b_api_key,
)
raise ProviderUnavailableError(
f"SANDBOX_PROVIDER='{provider}' پشتیبانی نمی‌شود. مقادیر مجاز: mock | daytona | e2b"
)
@lru_cache
def get_payment_provider():
provider = settings.payment_provider.lower()
if provider == "mock":
return mock.LocalMockPaymentAdapter()
if provider == "stripe":
from app.infrastructure.adapters.stripe_payments import StripePaymentAdapter
return StripePaymentAdapter(
secret_key=settings.stripe_secret_key,
webhook_secret=settings.stripe_webhook_secret,
)
raise ProviderUnavailableError(
f"PAYMENT_PROVIDER='{provider}' پشتیبانی نمی‌شود. مقادیر مجاز: mock | stripe"
)
@lru_cache
def get_storage():
return mock.InMemoryStorageAdapter()
@lru_cache
def get_vector_store():
return mock.InMemoryVectorStoreAdapter()
@lru_cache
def get_notifier():
return mock.ConsoleNotificationAdapter()
def reset_adapters() -> None:
"""Drop cached singletons. Used by tests that need a clean slate."""
for fn in (
get_model_provider,
get_git_provider,
get_domain_router,
get_sandbox_provider,
get_payment_provider,
get_storage,
get_vector_store,
get_notifier,
):
fn.cache_clear()