From 966df001247c750de2091afa8e435741e91b3561 Mon Sep 17 00:00:00 2001 From: Soulter <905617992@qq.com> Date: Fri, 10 Jan 2025 15:35:57 +0800 Subject: [PATCH] =?UTF-8?q?feat:=20=E6=94=AF=E6=8C=81=E4=BB=8E=E7=AE=A1?= =?UTF-8?q?=E7=90=86=E9=9D=A2=E6=9D=BF=EF=BC=88=E6=8E=A7=E5=88=B6=E5=8F=B0?= =?UTF-8?q?=E9=A1=B5=EF=BC=89=E6=89=8B=E5=8A=A8=E5=AE=89=E8=A3=85=20pip=20?= =?UTF-8?q?=E5=BA=93?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .gitignore | 3 +- astrbot/core/__init__.py | 4 ++ astrbot/core/core_lifecycle.py | 3 +- astrbot/core/star/star_manager.py | 15 ++----- astrbot/core/utils/pip_installer.py | 33 ++++++++++++++ astrbot/dashboard/routes/update.py | 15 ++++++- dashboard/src/views/ConsolePage.vue | 62 ++++++++++++++++++++++++++- dashboard/src/views/ExtensionPage.vue | 6 +-- main.py | 2 - 9 files changed, 122 insertions(+), 21 deletions(-) create mode 100644 astrbot/core/utils/pip_installer.py diff --git a/.gitignore b/.gitignore index aaf95b1a4..8d004e5c3 100644 --- a/.gitignore +++ b/.gitignore @@ -20,4 +20,5 @@ chroma node_modules/ .DS_Store package-lock.json -package.json \ No newline at end of file +package.json +venv/* \ No newline at end of file diff --git a/astrbot/core/__init__.py b/astrbot/core/__init__.py index f7876a78a..f11165f03 100644 --- a/astrbot/core/__init__.py +++ b/astrbot/core/__init__.py @@ -2,11 +2,14 @@ import os from .log import LogManager, LogBroker from astrbot.core.utils.t2i.renderer import HtmlRenderer from astrbot.core.utils.shared_preferences import SharedPreferences +from astrbot.core.utils.pip_installer import PipInstaller from astrbot.core.db.sqlite import SQLiteDatabase from astrbot.core.config.default import DB_PATH +from astrbot.core.config import AstrBotConfig os.makedirs("data", exist_ok=True) +astrbot_config = AstrBotConfig() html_renderer = HtmlRenderer() logger = LogManager.GetLogger(log_name='astrbot') @@ -15,4 +18,5 @@ if os.environ.get('TESTING', ""): db_helper = SQLiteDatabase(DB_PATH) sp = SharedPreferences() # 简单的偏好设置存储 +pip_installer = PipInstaller(astrbot_config.get('pip_install_arg', '')) WEBUI_SK = "Advanced_System_for_Text_Response_and_Bot_Operations_Tool" diff --git a/astrbot/core/core_lifecycle.py b/astrbot/core/core_lifecycle.py index 1e6948355..6783875a4 100644 --- a/astrbot/core/core_lifecycle.py +++ b/astrbot/core/core_lifecycle.py @@ -3,6 +3,7 @@ import time import threading import os from .event_bus import EventBus +from . import astrbot_config from asyncio import Queue from typing import List from astrbot.core.config.astrbot_config import AstrBotConfig @@ -21,7 +22,7 @@ from astrbot.core.rag.knowledge_db_mgr import KnowledgeDBManager class AstrBotCoreLifecycle: def __init__(self, log_broker: LogBroker, db: BaseDatabase): self.log_broker = log_broker - self.astrbot_config = AstrBotConfig() + self.astrbot_config = astrbot_config self.db = db if self.astrbot_config['http_proxy']: diff --git a/astrbot/core/star/star_manager.py b/astrbot/core/star/star_manager.py index ed5655af2..d5fc2f3fa 100644 --- a/astrbot/core/star/star_manager.py +++ b/astrbot/core/star/star_manager.py @@ -9,7 +9,7 @@ from types import ModuleType from typing import List from pip import main as pip_main from astrbot.core.config.astrbot_config import AstrBotConfig -from astrbot.core import logger, sp +from astrbot.core import logger, sp, pip_installer from .context import Context from . import StarMetadata from .updator import PluginUpdator @@ -92,21 +92,12 @@ class PluginManager: plugin_path = os.path.join(plugin_dir, p) if os.path.exists(os.path.join(plugin_path, "requirements.txt")): pth = os.path.join(plugin_path, "requirements.txt") - logger.info(f"正在检查插件 {p} 的依赖: {pth}") + logger.info(f"正在安装插件 {p} 所需的依赖库: {pth}") try: - self._update_plugin_dept(os.path.join(plugin_path, "requirements.txt")) + pip_installer.install(requirements_path=pth) except Exception as e: logger.error(f"更新插件 {p} 的依赖失败。Code: {str(e)}") - def _update_plugin_dept(self, path): - '''更新插件的依赖''' - args = ['install', '-r', path, '--trusted-host', 'mirrors.aliyun.com', '-i', 'https://mirrors.aliyun.com/pypi/simple/'] - if self.config.pip_install_arg: - args.extend([self.config.pip_install_arg]) - result_code = pip_main(args) - if result_code != 0: - raise Exception(str(result_code)) - def _load_plugin_metadata(self, plugin_path: str, plugin_obj = None) -> StarMetadata: '''v3.4.0 以前的方式载入插件元数据 diff --git a/astrbot/core/utils/pip_installer.py b/astrbot/core/utils/pip_installer.py new file mode 100644 index 000000000..cf595d512 --- /dev/null +++ b/astrbot/core/utils/pip_installer.py @@ -0,0 +1,33 @@ +import logging +from pip import main as pip_main + +class PipInstaller(): + def __init__(self, pip_install_arg: str): + self.pip_install_arg = pip_install_arg + + def install(self, package_name: str = None, requirements_path: str = None, mirror: str = None): + args = ['install'] + if package_name: + args.append(package_name) + elif requirements_path: + args.extend(['-r', requirements_path]) + + if not mirror: + mirror = 'https://mirrors.aliyun.com/pypi/simple/' + + args.extend(['--trusted-host', 'mirrors.aliyun.com', '-i', mirror]) + + if self.pip_install_arg: + args.extend(self.pip_install_arg.split()) + + print(f"Pip 包管理器: {' '.join(args)}") + + result_code = pip_main(args) + + # 清除 pip.main 导致的多余的 logging handlers + for handler in logging.root.handlers[:]: + logging.root.removeHandler(handler) + + if result_code != 0: + raise Exception(f"安装失败,错误码:{result_code}") + \ No newline at end of file diff --git a/astrbot/dashboard/routes/update.py b/astrbot/dashboard/routes/update.py index 03f241de4..2494ee6bf 100644 --- a/astrbot/dashboard/routes/update.py +++ b/astrbot/dashboard/routes/update.py @@ -3,7 +3,7 @@ import traceback from .route import Route, Response, RouteContext from quart import request from astrbot.core.updator import AstrBotUpdator -from astrbot.core import logger +from astrbot.core import logger, pip_installer class UpdateRoute(Route): def __init__(self, context: RouteContext, astrbot_updator: AstrBotUpdator) -> None: @@ -11,6 +11,7 @@ class UpdateRoute(Route): self.routes = { '/update/check': ('GET', self.check_update), '/update/do': ('POST', self.update_project), + '/update/pip-install': ('POST', self.install_pip_package) } self.astrbot_updator = astrbot_updator self.register_routes() @@ -47,4 +48,16 @@ class UpdateRoute(Route): return Response().ok(None, "更新成功,AstrBot 将在下次启动时应用新的代码。").__dict__ except Exception as e: logger.error(f"/api/update_project: {traceback.format_exc()}") + return Response().error(e.__str__()).__dict__ + + async def install_pip_package(self): + data = await request.json + package = data.get('package', '') + if not package: + return Response().error("缺少参数 package 或不合法。").__dict__ + try: + pip_installer.install(package) + return Response().ok(None, "安装成功。").__dict__ + except Exception as e: + logger.error(f"/api/update_pip: {traceback.format_exc()}") return Response().error(e.__str__()).__dict__ \ No newline at end of file diff --git a/dashboard/src/views/ConsolePage.vue b/dashboard/src/views/ConsolePage.vue index 9732a0f6f..5c6d58281 100644 --- a/dashboard/src/views/ConsolePage.vue +++ b/dashboard/src/views/ConsolePage.vue @@ -1,5 +1,7 @@ @@ -26,10 +84,12 @@ export default { from { opacity: 0; } + to { opacity: 1; } } + .fade-in { animation: fadeIn 0.2s ease-in-out; } diff --git a/dashboard/src/views/ExtensionPage.vue b/dashboard/src/views/ExtensionPage.vue index 69b6295a2..b584acb89 100644 --- a/dashboard/src/views/ExtensionPage.vue +++ b/dashboard/src/views/ExtensionPage.vue @@ -9,8 +9,8 @@ import axios from 'axios';