From 7174742886e061296f9dd14e8666ef01bd286b3f Mon Sep 17 00:00:00 2001 From: Junyan Qin <1010553892@qq.com> Date: Tue, 15 Oct 2024 00:07:40 +0800 Subject: [PATCH] =?UTF-8?q?feat:=20settings=20=E5=9F=BA=E7=A1=80=E7=BB=84?= =?UTF-8?q?=E4=BB=B6?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- pkg/api/http/controller/groups/settings.py | 41 ++++++++++ pkg/api/http/controller/groups/system.py | 2 +- pkg/api/http/controller/main.py | 2 +- pkg/config/manager.py | 14 +++- pkg/config/settings.py | 73 +++++++++++++++++ pkg/core/app.py | 3 + pkg/core/stages/load_config.py | 35 ++++++++ web/src/pages/Logs.vue | 4 +- web/src/pages/Settings.vue | 93 +++++++++++++++++++++- 9 files changed, 258 insertions(+), 9 deletions(-) create mode 100644 pkg/api/http/controller/groups/settings.py create mode 100644 pkg/config/settings.py diff --git a/pkg/api/http/controller/groups/settings.py b/pkg/api/http/controller/groups/settings.py new file mode 100644 index 00000000..15a145d2 --- /dev/null +++ b/pkg/api/http/controller/groups/settings.py @@ -0,0 +1,41 @@ +import quart + +from .....core import app +from .. import group + + +@group.group_class('settings', '/api/v1/settings') +class SettingsRouterGroup(group.RouterGroup): + + async def initialize(self) -> None: + + @self.route('', methods=['GET']) + async def _() -> str: + return self.success( + data={ + "managers": [ + { + "name": m.name, + "description": m.description, + } + for m in self.ap.settings_mgr.get_manager_list() + ] + } + ) + + @self.route('/', methods=['GET']) + async def _(manager_name: str) -> str: + + manager = self.ap.settings_mgr.get_manager(manager_name) + + return self.success( + data={ + "manager": { + "name": manager.name, + "description": manager.description, + "schema": manager.schema, + "file": manager.file.config_file_name, + "data": manager.data + } + } + ) diff --git a/pkg/api/http/controller/groups/system.py b/pkg/api/http/controller/groups/system.py index 43b06ddd..5575d06e 100644 --- a/pkg/api/http/controller/groups/system.py +++ b/pkg/api/http/controller/groups/system.py @@ -16,4 +16,4 @@ class SystemRouterGroup(group.RouterGroup): "version": constants.semantic_version, "debug": constants.debug_mode } - ) \ No newline at end of file + ) diff --git a/pkg/api/http/controller/main.py b/pkg/api/http/controller/main.py index 76545832..ac82a98e 100644 --- a/pkg/api/http/controller/main.py +++ b/pkg/api/http/controller/main.py @@ -5,7 +5,7 @@ import asyncio import quart from ....core import app -from .groups import logs, system +from .groups import logs, system, settings from . import group diff --git a/pkg/config/manager.py b/pkg/config/manager.py index 88ed6525..41c815c6 100644 --- a/pkg/config/manager.py +++ b/pkg/config/manager.py @@ -4,11 +4,19 @@ from . import model as file_model from .impls import pymodule, json as json_file, yaml as yaml_file -managers: ConfigManager = [] - - class ConfigManager: """配置文件管理器""" + + name: str = None + """配置管理器名""" + + description: str = None + """配置管理器描述""" + + schema: dict = None + """配置文件 schema + 需要符合 JSON Schema Draft 7 规范 + """ file: file_model.ConfigFile = None """配置文件实例""" diff --git a/pkg/config/settings.py b/pkg/config/settings.py new file mode 100644 index 00000000..9d1a0cbc --- /dev/null +++ b/pkg/config/settings.py @@ -0,0 +1,73 @@ +from __future__ import annotations + +from . import manager as config_manager +from ..core import app + + +class SettingsManager: + """设置管理器 + 保存、管理多个配置文件管理器 + """ + + ap: app.Application + + managers: list[config_manager.ConfigManager] = [] + """配置文件管理器列表""" + + def __init__(self, ap: app.Application) -> None: + self.ap = ap + self.managers = [] + + async def initialize(self) -> None: + pass + + def register_manager( + self, + name: str, + description: str, + manager: config_manager.ConfigManager, + schema: dict=None, + ) -> None: + """注册配置管理器 + + Args: + name (str): 配置管理器名 + description (str): 配置管理器描述 + manager (ConfigManager): 配置管理器 + schema (dict): 配置文件 schema,符合 JSON Schema Draft 7 规范 + """ + + for m in self.managers: + if m.name == name: + raise ValueError(f'配置管理器名 {name} 已存在') + + manager.name = name + manager.description = description + manager.schema = schema + self.managers.append(manager) + + def get_manager(self, name: str) -> config_manager.ConfigManager: + """获取配置管理器 + + Args: + name (str): 配置管理器名 + + Returns: + ConfigManager: 配置管理器 + """ + + for m in self.managers: + if m.name == name: + return m + + raise ValueError(f'配置管理器 {name} 不存在') + + def get_manager_list(self) -> list[config_manager.ConfigManager]: + """获取配置管理器列表 + + Returns: + list[ConfigManager]: 配置管理器列表 + """ + + return self.managers + diff --git a/pkg/core/app.py b/pkg/core/app.py index 2f0e0340..11a1eed3 100644 --- a/pkg/core/app.py +++ b/pkg/core/app.py @@ -11,6 +11,7 @@ from ..provider.sysprompt import sysprompt as llm_prompt_mgr from ..provider.tools import toolmgr as llm_tool_mgr from ..provider import runnermgr from ..config import manager as config_mgr +from ..config import settings as settings_mgr from ..audit.center import v2 as center_mgr from ..command import cmdmgr from ..plugin import manager as plugin_mgr @@ -43,6 +44,8 @@ class Application: runner_mgr: runnermgr.RunnerManager = None + settings_mgr: settings_mgr.SettingsManager = None + # ======= 配置管理器 ======= command_cfg: config_mgr.ConfigManager = None diff --git a/pkg/core/stages/load_config.py b/pkg/core/stages/load_config.py index cb6e1ed0..006af00f 100644 --- a/pkg/core/stages/load_config.py +++ b/pkg/core/stages/load_config.py @@ -2,6 +2,7 @@ from __future__ import annotations from .. import stage, app from ..bootutils import config +from ...config import settings as settings_mgr @stage.stage_class("LoadConfigStage") @@ -12,12 +13,46 @@ class LoadConfigStage(stage.BootingStage): async def run(self, ap: app.Application): """启动 """ + + ap.settings_mgr = settings_mgr.SettingsManager(ap) + await ap.settings_mgr.initialize() + ap.command_cfg = await config.load_json_config("data/config/command.json", "templates/command.json", completion=False) ap.pipeline_cfg = await config.load_json_config("data/config/pipeline.json", "templates/pipeline.json", completion=False) ap.platform_cfg = await config.load_json_config("data/config/platform.json", "templates/platform.json", completion=False) ap.provider_cfg = await config.load_json_config("data/config/provider.json", "templates/provider.json", completion=False) ap.system_cfg = await config.load_json_config("data/config/system.json", "templates/system.json", completion=False) + ap.settings_mgr.register_manager( + name="command.json", + description="命令配置", + manager=ap.command_cfg + ) + + ap.settings_mgr.register_manager( + name="pipeline.json", + description="消息处理流水线配置", + manager=ap.pipeline_cfg + ) + + ap.settings_mgr.register_manager( + name="platform.json", + description="消息平台配置", + manager=ap.platform_cfg + ) + + ap.settings_mgr.register_manager( + name="provider.json", + description="大模型能力配置", + manager=ap.provider_cfg + ) + + ap.settings_mgr.register_manager( + name="system.json", + description="系统配置", + manager=ap.system_cfg + ) + ap.plugin_setting_meta = await config.load_json_config("plugins/plugins.json", "templates/plugin-settings.json") await ap.plugin_setting_meta.dump_config() diff --git a/web/src/pages/Logs.vue b/web/src/pages/Logs.vue index aeaff77d..f76486f6 100644 --- a/web/src/pages/Logs.vue +++ b/web/src/pages/Logs.vue @@ -68,7 +68,7 @@ onUnmounted(() => { margin: 1rem; margin-top: 1rem; height: 3rem; - border-radius: 1rem; + border-radius: 0.3rem; } .toolbar-component { @@ -80,7 +80,7 @@ onUnmounted(() => { margin: 1rem; margin-top: 1rem; height: calc(100vh - 9.5rem); - border-radius: 1rem; + border-radius: 0.3rem; } diff --git a/web/src/pages/Settings.vue b/web/src/pages/Settings.vue index 7cb2711b..67d15856 100644 --- a/web/src/pages/Settings.vue +++ b/web/src/pages/Settings.vue @@ -1,13 +1,102 @@ +#settings-tabs { + height: 3rem; + overflow: hidden; +} + +#settings-tab-window { + height: calc(100vh - 9rem); + overflow: hidden; + /* background-color: aqua; */ +} + +.config-tab-window { + overflow: auto; +} + +.config-tab-toolbar { + margin: 0.5rem; + height: 4rem; + display: flex; + flex-direction: row; + justify-content: flex-start; + align-items: center; +} + +#config-type-toggle { + margin: 0.5rem; + box-shadow: 0 0 0 2px #dddddd; +} + +.config-type-toggle-btn {} + +.config-tab-content { + margin: 0.2rem; +} + \ No newline at end of file