Files
AstrBot/astrbot/core/__init__.py
LIghtJUNction a3fbfd3540 feat: SDK integration and various improvements
- Refactor core modules for better SDK integration
- Improve skill manager with better caching and loading
- Update dashboard routes for plugin and tools management
- Fix and enhance computer skill synchronization
- Various bug fixes and test improvements
2026-03-22 23:38:27 +08:00

228 lines
7.7 KiB
Python

from __future__ import annotations
import os
from importlib import import_module
from typing import TYPE_CHECKING, Any
from astrbot.core.config import AstrBotConfig
from astrbot.core.config.default import DB_PATH
from astrbot.core.db.sqlite import SQLiteDatabase
from astrbot.core.file_token_service import FileTokenService
from astrbot.core.utils.pip_installer import (
DependencyConflictError as DependencyConflictError,
)
from astrbot.core.utils.pip_installer import (
PipInstaller,
)
from astrbot.core.utils.requirements_utils import (
RequirementsPrecheckFailed as RequirementsPrecheckFailed,
)
from astrbot.core.utils.requirements_utils import (
find_missing_requirements as find_missing_requirements,
)
from astrbot.core.utils.requirements_utils import (
find_missing_requirements_or_raise as find_missing_requirements_or_raise,
)
from astrbot.core.utils.shared_preferences import SharedPreferences
from astrbot.core.utils.t2i.renderer import HtmlRenderer
from .log import LogBroker, LogManager
from .utils.astrbot_path import (
get_astrbot_config_path,
get_astrbot_data_path,
get_astrbot_knowledge_base_path,
get_astrbot_plugin_path,
get_astrbot_site_packages_path,
get_astrbot_skills_path,
get_astrbot_temp_path,
)
if TYPE_CHECKING:
from .config import AstrBotConfig
from .db.sqlite import SQLiteDatabase
from .file_token_service import FileTokenService
from .log import LogBroker, LogManager
from .utils.pip_installer import DependencyConflictError, PipInstaller
from .utils.requirements_utils import (
RequirementsPrecheckFailed,
find_missing_requirements,
find_missing_requirements_or_raise,
)
else:
AstrBotConfig: Any
SQLiteDatabase: Any
FileTokenService: Any
LogBroker: Any
LogManager: Any
DependencyConflictError: Any
PipInstaller: Any
RequirementsPrecheckFailed: Any
find_missing_requirements: Any
find_missing_requirements_or_raise: Any
astrbot_config: Any
db_helper: Any
file_token_service: Any
html_renderer: Any
logger: Any
pip_installer: Any
sp: Any
os.makedirs(get_astrbot_data_path(), exist_ok=True)
DEMO_MODE = os.getenv("DEMO_MODE", "False").strip().lower() in ("true", "1", "t")
# Initialize required data directories eagerly so later agent/tool flows do not
# fail on missing paths when the runtime root resolves to a fresh location.
for required_dir in (
get_astrbot_data_path(),
get_astrbot_config_path(),
get_astrbot_plugin_path(),
get_astrbot_temp_path(),
get_astrbot_knowledge_base_path(),
get_astrbot_skills_path(),
get_astrbot_site_packages_path(),
):
os.makedirs(required_dir, exist_ok=True)
astrbot_config = AstrBotConfig()
t2i_base_url = astrbot_config.get("t2i_endpoint", "https://t2i.soulter.top/text2img")
html_renderer = HtmlRenderer(t2i_base_url)
logger = LogManager.GetLogger(log_name="astrbot")
LogManager.configure_logger(
logger, astrbot_config, override_level=os.getenv("ASTRBOT_LOG_LEVEL")
)
LogManager.configure_trace_logger(astrbot_config)
db_helper = SQLiteDatabase(DB_PATH)
# 简单的偏好设置存储, 这里后续应该存储到数据库中, 一些部分可以存储到配置中
sp = SharedPreferences(db_helper=db_helper)
# 文件令牌服务
file_token_service = FileTokenService()
pip_installer = PipInstaller(
astrbot_config.get("pip_install_arg", ""),
astrbot_config.get("pypi_index_url", None),
)
_SINGLETON_CACHE: dict[str, Any] = {}
def _get_astrbot_config():
config_module = import_module(".config", __name__)
cached = _SINGLETON_CACHE.get("astrbot_config")
if cached is None:
cached = config_module.AstrBotConfig()
_SINGLETON_CACHE["astrbot_config"] = cached
return cached
def _get_log_manager():
return import_module(".log", __name__).LogManager
def _get_logger():
cached = _SINGLETON_CACHE.get("logger")
if cached is None:
logger_obj = _get_log_manager().GetLogger(log_name="astrbot")
config = _get_astrbot_config()
log_manager = _get_log_manager()
log_manager.configure_logger(logger_obj, config)
log_manager.configure_trace_logger(config)
_SINGLETON_CACHE["logger"] = logger_obj
cached = logger_obj
return cached
def _get_db_helper():
cached = _SINGLETON_CACHE.get("db_helper")
if cached is None:
sqlite_module = import_module(".db.sqlite", __name__)
default_module = import_module(".config.default", __name__)
cached = sqlite_module.SQLiteDatabase(default_module.DB_PATH)
_SINGLETON_CACHE["db_helper"] = cached
return cached
def _get_shared_preferences():
cached = _SINGLETON_CACHE.get("sp")
if cached is None:
shared_preferences_module = import_module(".utils.shared_preferences", __name__)
cached = shared_preferences_module.SharedPreferences(db_helper=_get_db_helper())
_SINGLETON_CACHE["sp"] = cached
return cached
def _get_file_token_service():
cached = _SINGLETON_CACHE.get("file_token_service")
if cached is None:
service_module = import_module(".file_token_service", __name__)
cached = service_module.FileTokenService()
_SINGLETON_CACHE["file_token_service"] = cached
return cached
def _get_html_renderer():
cached = _SINGLETON_CACHE.get("html_renderer")
if cached is None:
renderer_module = import_module(".utils.t2i.renderer", __name__)
config = _get_astrbot_config()
endpoint = config.get("t2i_endpoint", "https://t2i.soulter.top/text2img")
cached = renderer_module.HtmlRenderer(endpoint)
_SINGLETON_CACHE["html_renderer"] = cached
return cached
def _get_pip_installer():
cached = _SINGLETON_CACHE.get("pip_installer")
if cached is None:
installer_module = import_module(".utils.pip_installer", __name__)
config = _get_astrbot_config()
cached = installer_module.PipInstaller(
config.get("pip_install_arg", ""),
config.get("pypi_index_url", None),
)
_SINGLETON_CACHE["pip_installer"] = cached
return cached
def __getattr__(name: str) -> Any:
if name == "AstrBotConfig":
return import_module(".config", __name__).AstrBotConfig
if name in {"LogBroker", "LogManager"}:
module = import_module(".log", __name__)
return getattr(module, name)
if name == "DependencyConflictError":
return import_module(".utils.pip_installer", __name__).DependencyConflictError
if name == "FileTokenService":
return import_module(".file_token_service", __name__).FileTokenService
if name == "PipInstaller":
return import_module(".utils.pip_installer", __name__).PipInstaller
if name == "RequirementsPrecheckFailed":
return import_module(
".utils.requirements_utils", __name__
).RequirementsPrecheckFailed
if name == "SQLiteDatabase":
return import_module(".db.sqlite", __name__).SQLiteDatabase
if name == "find_missing_requirements":
return import_module(
".utils.requirements_utils", __name__
).find_missing_requirements
if name == "find_missing_requirements_or_raise":
return import_module(
".utils.requirements_utils", __name__
).find_missing_requirements_or_raise
if name == "astrbot_config":
return _get_astrbot_config()
if name == "logger":
return _get_logger()
if name == "db_helper":
return _get_db_helper()
if name == "sp":
return _get_shared_preferences()
if name == "file_token_service":
return _get_file_token_service()
if name == "html_renderer":
return _get_html_renderer()
if name == "pip_installer":
return _get_pip_installer()
raise AttributeError(name)