feat: 多平台 Coding Plan 统一管理系统初始实现
- 支持 MiniMax/OpenAI/Google Gemini/智谱/Kimi 五个平台 - 插件化 Provider 架构,自动发现注册 - 多维度 QuotaRule 额度追踪(固定间隔/自然周期/API同步/手动) - OpenAI + Anthropic 兼容 API 代理,SSE 流式转发 - Model 路由表 + 额度耗尽自动 fallback - 多媒体任务队列(图片/语音/视频) - Vue3 + Tailwind 单文件 Web 仪表盘 - Docker 一键部署 Made-with: Cursor
This commit is contained in:
@@ -0,0 +1,50 @@
|
||||
"""Provider 自动发现 + 注册表"""
|
||||
|
||||
from __future__ import annotations
|
||||
|
||||
import importlib
|
||||
import pkgutil
|
||||
from pathlib import Path
|
||||
from typing import TYPE_CHECKING
|
||||
|
||||
if TYPE_CHECKING:
|
||||
from app.providers.base import BaseProvider, Capability
|
||||
|
||||
|
||||
class ProviderRegistry:
|
||||
"""全局 Provider 注册表,启动时自动扫描 providers/ 目录"""
|
||||
|
||||
_providers: dict[str, "BaseProvider"] = {}
|
||||
|
||||
@classmethod
|
||||
def auto_discover(cls):
|
||||
"""扫描当前包下所有模块,注册 BaseProvider 子类实例"""
|
||||
from app.providers.base import BaseProvider as _Base
|
||||
|
||||
package_dir = Path(__file__).parent
|
||||
for info in pkgutil.iter_modules([str(package_dir)]):
|
||||
if info.name in ("base", "__init__"):
|
||||
continue
|
||||
mod = importlib.import_module(f"app.providers.{info.name}")
|
||||
for attr_name in dir(mod):
|
||||
attr = getattr(mod, attr_name)
|
||||
if (
|
||||
isinstance(attr, type)
|
||||
and issubclass(attr, _Base)
|
||||
and attr is not _Base
|
||||
and getattr(attr, "name", "")
|
||||
):
|
||||
instance = attr()
|
||||
cls._providers[instance.name] = instance
|
||||
|
||||
@classmethod
|
||||
def get(cls, name: str) -> "BaseProvider | None":
|
||||
return cls._providers.get(name)
|
||||
|
||||
@classmethod
|
||||
def all(cls) -> dict[str, "BaseProvider"]:
|
||||
return dict(cls._providers)
|
||||
|
||||
@classmethod
|
||||
def by_capability(cls, cap: "Capability") -> list["BaseProvider"]:
|
||||
return [p for p in cls._providers.values() if cap in p.capabilities]
|
||||
Reference in New Issue
Block a user