chore: switch comments to en

This commit is contained in:
Junyan Qin
2025-07-10 11:01:16 +08:00
parent 56248c350f
commit 4d0a39eb65
23 changed files with 119 additions and 111 deletions

View File

@@ -11,11 +11,11 @@ from ....core import app
preregistered_groups: list[type[RouterGroup]] = [] preregistered_groups: list[type[RouterGroup]] = []
"""RouterGroup 的预注册列表""" """Pre-registered list of RouterGroup"""
def group_class(name: str, path: str) -> None: def group_class(name: str, path: str) -> None:
"""注册一个 RouterGroup""" """Register a RouterGroup"""
def decorator(cls: typing.Type[RouterGroup]) -> typing.Type[RouterGroup]: def decorator(cls: typing.Type[RouterGroup]) -> typing.Type[RouterGroup]:
cls.name = name cls.name = name
@@ -27,7 +27,7 @@ def group_class(name: str, path: str) -> None:
class AuthType(enum.Enum): class AuthType(enum.Enum):
"""认证类型""" """Authentication type"""
NONE = 'none' NONE = 'none'
USER_TOKEN = 'user-token' USER_TOKEN = 'user-token'
@@ -56,7 +56,7 @@ class RouterGroup(abc.ABC):
auth_type: AuthType = AuthType.USER_TOKEN, auth_type: AuthType = AuthType.USER_TOKEN,
**options: typing.Any, **options: typing.Any,
) -> typing.Callable[[RouteCallable], RouteCallable]: # decorator ) -> typing.Callable[[RouteCallable], RouteCallable]: # decorator
"""注册一个路由""" """Register a route"""
def decorator(f: RouteCallable) -> RouteCallable: def decorator(f: RouteCallable) -> RouteCallable:
nonlocal rule nonlocal rule
@@ -64,11 +64,11 @@ class RouterGroup(abc.ABC):
async def handler_error(*args, **kwargs): async def handler_error(*args, **kwargs):
if auth_type == AuthType.USER_TOKEN: if auth_type == AuthType.USER_TOKEN:
# Authorization头中获取token # get token from Authorization header
token = quart.request.headers.get('Authorization', '').replace('Bearer ', '') token = quart.request.headers.get('Authorization', '').replace('Bearer ', '')
if not token: if not token:
return self.http_status(401, -1, '未提供有效的用户令牌') return self.http_status(401, -1, 'No valid user token provided')
try: try:
user_email = await self.ap.user_service.verify_jwt_token(token) user_email = await self.ap.user_service.verify_jwt_token(token)
@@ -76,9 +76,9 @@ class RouterGroup(abc.ABC):
# check if this account exists # check if this account exists
user = await self.ap.user_service.get_user_by_email(user_email) user = await self.ap.user_service.get_user_by_email(user_email)
if not user: if not user:
return self.http_status(401, -1, '用户不存在') return self.http_status(401, -1, 'User not found')
# 检查f是否接受user_email参数 # check if f accepts user_email parameter
if 'user_email' in f.__code__.co_varnames: if 'user_email' in f.__code__.co_varnames:
kwargs['user_email'] = user_email kwargs['user_email'] = user_email
except Exception as e: except Exception as e:
@@ -86,7 +86,7 @@ class RouterGroup(abc.ABC):
try: try:
return await f(*args, **kwargs) return await f(*args, **kwargs)
except Exception: # 自动 500 except Exception: # auto 500
traceback.print_exc() traceback.print_exc()
# return self.http_status(500, -2, str(e)) # return self.http_status(500, -2, str(e))
return self.http_status(500, -2, 'internal server error') return self.http_status(500, -2, 'internal server error')
@@ -101,7 +101,7 @@ class RouterGroup(abc.ABC):
return decorator return decorator
def success(self, data: typing.Any = None) -> quart.Response: def success(self, data: typing.Any = None) -> quart.Response:
"""返回一个 200 响应""" """Return a 200 response"""
return quart.jsonify( return quart.jsonify(
{ {
'code': 0, 'code': 0,
@@ -111,7 +111,7 @@ class RouterGroup(abc.ABC):
) )
def fail(self, code: int, msg: str) -> quart.Response: def fail(self, code: int, msg: str) -> quart.Response:
"""返回一个异常响应""" """Return an error response"""
return quart.jsonify( return quart.jsonify(
{ {
@@ -121,5 +121,5 @@ class RouterGroup(abc.ABC):
) )
def http_status(self, status: int, code: int, msg: str) -> quart.Response: def http_status(self, status: int, code: int, msg: str) -> quart.Response:
"""返回一个指定状态码的响应""" """Return a response with a specified status code"""
return self.fail(code, msg), status return self.fail(code, msg), status

View File

@@ -8,7 +8,7 @@ class WebChatDebugRouterGroup(group.RouterGroup):
async def initialize(self) -> None: async def initialize(self) -> None:
@self.route('/send', methods=['POST']) @self.route('/send', methods=['POST'])
async def send_message(pipeline_uuid: str) -> str: async def send_message(pipeline_uuid: str) -> str:
"""发送调试消息到流水线""" """Send a message to the pipeline for debugging"""
try: try:
data = await quart.request.get_json() data = await quart.request.get_json()
session_type = data.get('session_type', 'person') session_type = data.get('session_type', 'person')
@@ -38,7 +38,7 @@ class WebChatDebugRouterGroup(group.RouterGroup):
@self.route('/messages/<session_type>', methods=['GET']) @self.route('/messages/<session_type>', methods=['GET'])
async def get_messages(pipeline_uuid: str, session_type: str) -> str: async def get_messages(pipeline_uuid: str, session_type: str) -> str:
"""获取调试消息历史""" """Get the message history of the pipeline for debugging"""
try: try:
if session_type not in ['person', 'group']: if session_type not in ['person', 'group']:
return self.http_status(400, -1, 'session_type must be person or group') return self.http_status(400, -1, 'session_type must be person or group')
@@ -57,7 +57,7 @@ class WebChatDebugRouterGroup(group.RouterGroup):
@self.route('/reset/<session_type>', methods=['POST']) @self.route('/reset/<session_type>', methods=['POST'])
async def reset_session(session_type: str) -> str: async def reset_session(session_type: str) -> str:
"""重置调试会话""" """Reset the debug session"""
try: try:
if session_type not in ['person', 'group']: if session_type not in ['person', 'group']:
return self.http_status(400, -1, 'session_type must be person or group') return self.http_status(400, -1, 'session_type must be person or group')

View File

@@ -40,7 +40,7 @@ class PluginsRouterGroup(group.RouterGroup):
self.ap.plugin_mgr.update_plugin(plugin_name, task_context=ctx), self.ap.plugin_mgr.update_plugin(plugin_name, task_context=ctx),
kind='plugin-operation', kind='plugin-operation',
name=f'plugin-update-{plugin_name}', name=f'plugin-update-{plugin_name}',
label=f'更新插件 {plugin_name}', label=f'Updating plugin {plugin_name}',
context=ctx, context=ctx,
) )
return self.success(data={'task_id': wrapper.id}) return self.success(data={'task_id': wrapper.id})
@@ -62,7 +62,7 @@ class PluginsRouterGroup(group.RouterGroup):
self.ap.plugin_mgr.uninstall_plugin(plugin_name, task_context=ctx), self.ap.plugin_mgr.uninstall_plugin(plugin_name, task_context=ctx),
kind='plugin-operation', kind='plugin-operation',
name=f'plugin-remove-{plugin_name}', name=f'plugin-remove-{plugin_name}',
label=f'删除插件 {plugin_name}', label=f'Removing plugin {plugin_name}',
context=ctx, context=ctx,
) )
@@ -102,7 +102,7 @@ class PluginsRouterGroup(group.RouterGroup):
self.ap.plugin_mgr.install_plugin(data['source'], task_context=ctx), self.ap.plugin_mgr.install_plugin(data['source'], task_context=ctx),
kind='plugin-operation', kind='plugin-operation',
name='plugin-install-github', name='plugin-install-github',
label=f'安装插件 ...{short_source_str}', label=f'Installing plugin ...{short_source_str}',
context=ctx, context=ctx,
) )

View File

@@ -14,7 +14,7 @@ class UserRouterGroup(group.RouterGroup):
return self.success(data={'initialized': await self.ap.user_service.is_initialized()}) return self.success(data={'initialized': await self.ap.user_service.is_initialized()})
if await self.ap.user_service.is_initialized(): if await self.ap.user_service.is_initialized():
return self.fail(1, '系统已初始化') return self.fail(1, 'System already initialized')
json_data = await quart.request.json json_data = await quart.request.json
@@ -32,7 +32,7 @@ class UserRouterGroup(group.RouterGroup):
try: try:
token = await self.ap.user_service.authenticate(json_data['user'], json_data['password']) token = await self.ap.user_service.authenticate(json_data['user'], json_data['password'])
except argon2.exceptions.VerifyMismatchError: except argon2.exceptions.VerifyMismatchError:
return self.fail(1, '用户名或密码错误') return self.fail(1, 'Invalid username or password')
return self.success(data={'token': token}) return self.success(data={'token': token})
@@ -54,15 +54,15 @@ class UserRouterGroup(group.RouterGroup):
await asyncio.sleep(3) await asyncio.sleep(3)
if not await self.ap.user_service.is_initialized(): if not await self.ap.user_service.is_initialized():
return self.http_status(400, -1, 'system not initialized') return self.http_status(400, -1, 'System not initialized')
user_obj = await self.ap.user_service.get_user_by_email(user_email) user_obj = await self.ap.user_service.get_user_by_email(user_email)
if user_obj is None: if user_obj is None:
return self.http_status(400, -1, 'user not found') return self.http_status(400, -1, 'User not found')
if recovery_key != self.ap.instance_config.data['system']['recovery_key']: if recovery_key != self.ap.instance_config.data['system']['recovery_key']:
return self.http_status(403, -1, 'invalid recovery key') return self.http_status(403, -1, 'Invalid recovery key')
await self.ap.user_service.reset_password(user_email, new_password) await self.ap.user_service.reset_password(user_email, new_password)

View File

@@ -45,7 +45,7 @@ class HTTPController:
try: try:
await self.quart_app.run_task(*args, **kwargs) await self.quart_app.run_task(*args, **kwargs)
except Exception as e: except Exception as e:
self.ap.logger.error(f'启动 HTTP 服务失败: {e}') self.ap.logger.error(f'Failed to start HTTP service: {e}')
self.ap.task_mgr.create_task( self.ap.task_mgr.create_task(
exception_handler( exception_handler(

View File

@@ -10,7 +10,7 @@ from ....entity.persistence import pipeline as persistence_pipeline
class BotService: class BotService:
"""机器人服务""" """Bot service"""
ap: app.Application ap: app.Application
@@ -18,7 +18,7 @@ class BotService:
self.ap = ap self.ap = ap
async def get_bots(self) -> list[dict]: async def get_bots(self) -> list[dict]:
"""获取所有机器人""" """Get all bots"""
result = await self.ap.persistence_mgr.execute_async(sqlalchemy.select(persistence_bot.Bot)) result = await self.ap.persistence_mgr.execute_async(sqlalchemy.select(persistence_bot.Bot))
bots = result.all() bots = result.all()
@@ -26,7 +26,7 @@ class BotService:
return [self.ap.persistence_mgr.serialize_model(persistence_bot.Bot, bot) for bot in bots] return [self.ap.persistence_mgr.serialize_model(persistence_bot.Bot, bot) for bot in bots]
async def get_bot(self, bot_uuid: str) -> dict | None: async def get_bot(self, bot_uuid: str) -> dict | None:
"""获取机器人""" """Get bot"""
result = await self.ap.persistence_mgr.execute_async( result = await self.ap.persistence_mgr.execute_async(
sqlalchemy.select(persistence_bot.Bot).where(persistence_bot.Bot.uuid == bot_uuid) sqlalchemy.select(persistence_bot.Bot).where(persistence_bot.Bot.uuid == bot_uuid)
) )
@@ -39,7 +39,7 @@ class BotService:
return self.ap.persistence_mgr.serialize_model(persistence_bot.Bot, bot) return self.ap.persistence_mgr.serialize_model(persistence_bot.Bot, bot)
async def create_bot(self, bot_data: dict) -> str: async def create_bot(self, bot_data: dict) -> str:
"""创建机器人""" """Create bot"""
# TODO: 检查配置信息格式 # TODO: 检查配置信息格式
bot_data['uuid'] = str(uuid.uuid4()) bot_data['uuid'] = str(uuid.uuid4())
@@ -63,7 +63,7 @@ class BotService:
return bot_data['uuid'] return bot_data['uuid']
async def update_bot(self, bot_uuid: str, bot_data: dict) -> None: async def update_bot(self, bot_uuid: str, bot_data: dict) -> None:
"""更新机器人""" """Update bot"""
if 'uuid' in bot_data: if 'uuid' in bot_data:
del bot_data['uuid'] del bot_data['uuid']
@@ -99,7 +99,7 @@ class BotService:
session.using_conversation = None session.using_conversation = None
async def delete_bot(self, bot_uuid: str) -> None: async def delete_bot(self, bot_uuid: str) -> None:
"""删除机器人""" """Delete bot"""
await self.ap.platform_mgr.remove_bot(bot_uuid) await self.ap.platform_mgr.remove_bot(bot_uuid)
await self.ap.persistence_mgr.execute_async( await self.ap.persistence_mgr.execute_async(
sqlalchemy.delete(persistence_bot.Bot).where(persistence_bot.Bot.uuid == bot_uuid) sqlalchemy.delete(persistence_bot.Bot).where(persistence_bot.Bot.uuid == bot_uuid)

View File

@@ -6,7 +6,7 @@ from .. import model as file_model
class JSONConfigFile(file_model.ConfigFile): class JSONConfigFile(file_model.ConfigFile):
"""JSON配置文件""" """JSON config file"""
def __init__( def __init__(
self, self,
@@ -42,7 +42,7 @@ class JSONConfigFile(file_model.ConfigFile):
try: try:
cfg = json.load(f) cfg = json.load(f)
except json.JSONDecodeError as e: except json.JSONDecodeError as e:
raise Exception(f'配置文件 {self.config_file_name} 语法错误: {e}') raise Exception(f'Syntax error in config file {self.config_file_name}: {e}')
if completion: if completion:
for key in self.template_data: for key in self.template_data:

View File

@@ -7,13 +7,13 @@ from .. import model as file_model
class PythonModuleConfigFile(file_model.ConfigFile): class PythonModuleConfigFile(file_model.ConfigFile):
"""Python模块配置文件""" """Python module config file"""
config_file_name: str = None config_file_name: str = None
"""配置文件名""" """Config file name"""
template_file_name: str = None template_file_name: str = None
"""模板文件名""" """Template file name"""
def __init__(self, config_file_name: str, template_file_name: str) -> None: def __init__(self, config_file_name: str, template_file_name: str) -> None:
self.config_file_name = config_file_name self.config_file_name = config_file_name
@@ -42,7 +42,7 @@ class PythonModuleConfigFile(file_model.ConfigFile):
cfg[key] = getattr(module, key) cfg[key] = getattr(module, key)
# 从模板模块文件中进行补全 # complete from template module file
if completion: if completion:
module_name = os.path.splitext(os.path.basename(self.template_file_name))[0] module_name = os.path.splitext(os.path.basename(self.template_file_name))[0]
module = importlib.import_module(module_name) module = importlib.import_module(module_name)
@@ -60,7 +60,7 @@ class PythonModuleConfigFile(file_model.ConfigFile):
return cfg return cfg
async def save(self, data: dict): async def save(self, data: dict):
logging.warning('Python模块配置文件不支持保存') logging.warning('Python module config file does not support saving')
def save_sync(self, data: dict): def save_sync(self, data: dict):
logging.warning('Python模块配置文件不支持保存') logging.warning('Python module config file does not support saving')

View File

@@ -6,7 +6,7 @@ from .. import model as file_model
class YAMLConfigFile(file_model.ConfigFile): class YAMLConfigFile(file_model.ConfigFile):
"""YAML配置文件""" """YAML config file"""
def __init__( def __init__(
self, self,
@@ -42,7 +42,7 @@ class YAMLConfigFile(file_model.ConfigFile):
try: try:
cfg = yaml.load(f, Loader=yaml.FullLoader) cfg = yaml.load(f, Loader=yaml.FullLoader)
except yaml.YAMLError as e: except yaml.YAMLError as e:
raise Exception(f'配置文件 {self.config_file_name} 语法错误: {e}') raise Exception(f'Syntax error in config file {self.config_file_name}: {e}')
if completion: if completion:
for key in self.template_data: for key in self.template_data:

View File

@@ -5,27 +5,27 @@ from .impls import pymodule, json as json_file, yaml as yaml_file
class ConfigManager: class ConfigManager:
"""配置文件管理器""" """Config file manager"""
name: str = None name: str = None
"""配置管理器名""" """Config manager name"""
description: str = None description: str = None
"""配置管理器描述""" """Config manager description"""
schema: dict = None schema: dict = None
"""配置文件 schema """Config file schema
需要符合 JSON Schema Draft 7 规范 Must conform to JSON Schema Draft 7 specification
""" """
file: file_model.ConfigFile = None file: file_model.ConfigFile = None
"""配置文件实例""" """Config file instance"""
data: dict = None data: dict = None
"""配置数据""" """Config data"""
doc_link: str = None doc_link: str = None
"""配置文件文档链接""" """Config file documentation link"""
def __init__(self, cfg_file: file_model.ConfigFile) -> None: def __init__(self, cfg_file: file_model.ConfigFile) -> None:
self.file = cfg_file self.file = cfg_file
@@ -42,15 +42,15 @@ class ConfigManager:
async def load_python_module_config(config_name: str, template_name: str, completion: bool = True) -> ConfigManager: async def load_python_module_config(config_name: str, template_name: str, completion: bool = True) -> ConfigManager:
"""加载Python模块配置文件 """Load Python module config file
Args: Args:
config_name (str): 配置文件名 config_name (str): Config file name
template_name (str): 模板文件名 template_name (str): Template file name
completion (bool): 是否自动补全内存中的配置文件 completion (bool): Whether to automatically complete the config file in memory
Returns: Returns:
ConfigManager: 配置文件管理器 ConfigManager: Config file manager
""" """
cfg_inst = pymodule.PythonModuleConfigFile(config_name, template_name) cfg_inst = pymodule.PythonModuleConfigFile(config_name, template_name)
@@ -66,13 +66,13 @@ async def load_json_config(
template_data: dict = None, template_data: dict = None,
completion: bool = True, completion: bool = True,
) -> ConfigManager: ) -> ConfigManager:
"""加载JSON配置文件 """Load JSON config file
Args: Args:
config_name (str): 配置文件名 config_name (str): Config file name
template_name (str): 模板文件名 template_name (str): Template file name
template_data (dict): 模板数据 template_data (dict): Template data
completion (bool): 是否自动补全内存中的配置文件 completion (bool): Whether to automatically complete the config file in memory
""" """
cfg_inst = json_file.JSONConfigFile(config_name, template_name, template_data) cfg_inst = json_file.JSONConfigFile(config_name, template_name, template_data)
@@ -88,16 +88,16 @@ async def load_yaml_config(
template_data: dict = None, template_data: dict = None,
completion: bool = True, completion: bool = True,
) -> ConfigManager: ) -> ConfigManager:
"""加载YAML配置文件 """Load YAML config file
Args: Args:
config_name (str): 配置文件名 config_name (str): Config file name
template_name (str): 模板文件名 template_name (str): Template file name
template_data (dict): 模板数据 template_data (dict): Template data
completion (bool): 是否自动补全内存中的配置文件 completion (bool): Whether to automatically complete the config file in memory
Returns: Returns:
ConfigManager: 配置文件管理器 ConfigManager: Config file manager
""" """
cfg_inst = yaml_file.YAMLConfigFile(config_name, template_name, template_data) cfg_inst = yaml_file.YAMLConfigFile(config_name, template_name, template_data)

View File

@@ -2,16 +2,16 @@ import abc
class ConfigFile(metaclass=abc.ABCMeta): class ConfigFile(metaclass=abc.ABCMeta):
"""配置文件抽象类""" """Config file abstract class"""
config_file_name: str = None config_file_name: str = None
"""配置文件名""" """Config file name"""
template_file_name: str = None template_file_name: str = None
"""模板文件名""" """Template file name"""
template_data: dict = None template_data: dict = None
"""模板数据""" """Template data"""
@abc.abstractmethod @abc.abstractmethod
def exists(self) -> bool: def exists(self) -> bool:

View File

@@ -30,7 +30,7 @@ from . import entities as core_entities
class Application: class Application:
"""运行时应用对象和上下文""" """Runtime application object and context"""
event_loop: asyncio.AbstractEventLoop = None event_loop: asyncio.AbstractEventLoop = None
@@ -47,10 +47,10 @@ class Application:
model_mgr: llm_model_mgr.ModelManager = None model_mgr: llm_model_mgr.ModelManager = None
# TODO 移动到 pipeline # TODO move to pipeline
tool_mgr: llm_tool_mgr.ToolManager = None tool_mgr: llm_tool_mgr.ToolManager = None
# ======= 配置管理器 ======= # ======= Config manager =======
command_cfg: config_mgr.ConfigManager = None # deprecated command_cfg: config_mgr.ConfigManager = None # deprecated
@@ -64,7 +64,7 @@ class Application:
instance_config: config_mgr.ConfigManager = None instance_config: config_mgr.ConfigManager = None
# ======= 元数据配置管理器 ======= # ======= Metadata config manager =======
sensitive_meta: config_mgr.ConfigManager = None sensitive_meta: config_mgr.ConfigManager = None
@@ -154,11 +154,11 @@ class Application:
except asyncio.CancelledError: except asyncio.CancelledError:
pass pass
except Exception as e: except Exception as e:
self.logger.error(f'应用运行致命异常: {e}') self.logger.error(f'Application runtime fatal exception: {e}')
self.logger.debug(f'Traceback: {traceback.format_exc()}') self.logger.debug(f'Traceback: {traceback.format_exc()}')
async def print_web_access_info(self): async def print_web_access_info(self):
"""打印访问 webui 的提示""" """Print access webui tips"""
if not os.path.exists(os.path.join('.', 'web/out')): if not os.path.exists(os.path.join('.', 'web/out')):
self.logger.warning('WebUI 文件缺失请根据文档部署https://docs.langbot.app/zh') self.logger.warning('WebUI 文件缺失请根据文档部署https://docs.langbot.app/zh')
@@ -190,7 +190,7 @@ class Application:
): ):
match scope: match scope:
case core_entities.LifecycleControlScope.PLATFORM.value: case core_entities.LifecycleControlScope.PLATFORM.value:
self.logger.info('执行热重载 scope=' + scope) self.logger.info('Hot reload scope=' + scope)
await self.platform_mgr.shutdown() await self.platform_mgr.shutdown()
self.platform_mgr = im_mgr.PlatformManager(self) self.platform_mgr = im_mgr.PlatformManager(self)
@@ -206,7 +206,7 @@ class Application:
], ],
) )
case core_entities.LifecycleControlScope.PLUGIN.value: case core_entities.LifecycleControlScope.PLUGIN.value:
self.logger.info('执行热重载 scope=' + scope) self.logger.info('Hot reload scope=' + scope)
await self.plugin_mgr.destroy_plugins() await self.plugin_mgr.destroy_plugins()
# 删除 sys.module 中所有的 plugins/* 下的模块 # 删除 sys.module 中所有的 plugins/* 下的模块
@@ -222,7 +222,7 @@ class Application:
await self.plugin_mgr.load_plugins() await self.plugin_mgr.load_plugins()
await self.plugin_mgr.initialize_plugins() await self.plugin_mgr.initialize_plugins()
case core_entities.LifecycleControlScope.PROVIDER.value: case core_entities.LifecycleControlScope.PROVIDER.value:
self.logger.info('执行热重载 scope=' + scope) self.logger.info('Hot reload scope=' + scope)
await self.tool_mgr.shutdown() await self.tool_mgr.shutdown()

View File

@@ -8,7 +8,7 @@ from . import app
from . import stage from . import stage
from ..utils import constants, importutil from ..utils import constants, importutil
# 引入启动阶段实现以便注册 # Import startup stage implementation to register
from . import stages from . import stages
importutil.import_modules_in_pkg(stages) importutil.import_modules_in_pkg(stages)
@@ -25,7 +25,7 @@ stage_order = [
async def make_app(loop: asyncio.AbstractEventLoop) -> app.Application: async def make_app(loop: asyncio.AbstractEventLoop) -> app.Application:
# 确定是否为调试模式 # Determine if it is debug mode
if 'DEBUG' in os.environ and os.environ['DEBUG'] in ['true', '1']: if 'DEBUG' in os.environ and os.environ['DEBUG'] in ['true', '1']:
constants.debug_mode = True constants.debug_mode = True
@@ -33,7 +33,7 @@ async def make_app(loop: asyncio.AbstractEventLoop) -> app.Application:
ap.event_loop = loop ap.event_loop = loop
# 执行启动阶段 # Execute startup stage
for stage_name in stage_order: for stage_name in stage_order:
stage_cls = stage.preregistered_stages[stage_name] stage_cls = stage.preregistered_stages[stage_name]
stage_inst = stage_cls() stage_inst = stage_cls()
@@ -47,11 +47,11 @@ async def make_app(loop: asyncio.AbstractEventLoop) -> app.Application:
async def main(loop: asyncio.AbstractEventLoop): async def main(loop: asyncio.AbstractEventLoop):
try: try:
# 挂系统信号处理 # Hang system signal processing
import signal import signal
def signal_handler(sig, frame): def signal_handler(sig, frame):
print('[Signal] 程序退出.') print('[Signal] Program exit.')
# ap.shutdown() # ap.shutdown()
os._exit(0) os._exit(0)

View File

@@ -2,8 +2,8 @@ import pip
import os import os
from ...utils import pkgmgr from ...utils import pkgmgr
# 检查依赖,防止用户未安装 # Check dependencies to prevent users from not installing
# 左边为引入名称,右边为依赖名称 # Left is the import name, right is the dependency name
required_deps = { required_deps = {
'requests': 'requests', 'requests': 'requests',
'openai': 'openai', 'openai': 'openai',
@@ -65,7 +65,7 @@ async def install_deps(deps: list[str]):
async def precheck_plugin_deps(): async def precheck_plugin_deps():
print('[Startup] Prechecking plugin dependencies...') print('[Startup] Prechecking plugin dependencies...')
# 只有在plugins目录存在时才执行插件依赖安装 # Only execute plugin dependency installation when the plugins directory exists
if os.path.exists('plugins'): if os.path.exists('plugins'):
for dir in os.listdir('plugins'): for dir in os.listdir('plugins'):
subdir = os.path.join('plugins', dir) subdir = os.path.join('plugins', dir)

View File

@@ -17,7 +17,7 @@ log_colors_config = {
async def init_logging(extra_handlers: list[logging.Handler] = None) -> logging.Logger: async def init_logging(extra_handlers: list[logging.Handler] = None) -> logging.Logger:
# 删除所有现有的logger # Remove all existing loggers
for handler in logging.root.handlers[:]: for handler in logging.root.handlers[:]:
logging.root.removeHandler(handler) logging.root.removeHandler(handler)
@@ -54,13 +54,13 @@ async def init_logging(extra_handlers: list[logging.Handler] = None) -> logging.
handler.setFormatter(color_formatter) handler.setFormatter(color_formatter)
qcg_logger.addHandler(handler) qcg_logger.addHandler(handler)
qcg_logger.debug('日志初始化完成,日志级别:%s' % level) qcg_logger.debug('Logging initialized, log level: %s' % level)
logging.basicConfig( logging.basicConfig(
level=logging.CRITICAL, # 设置日志输出格式 level=logging.CRITICAL, # Set log output format
format='[DEPR][%(asctime)s.%(msecs)03d] %(pathname)s (%(lineno)d) - [%(levelname)s] :\n%(message)s', format='[DEPR][%(asctime)s.%(msecs)03d] %(pathname)s (%(lineno)d) - [%(levelname)s] :\n%(message)s',
# 日志输出的格式 # Log output format
# -8表示占位符让输出左对齐输出长度都为8位 # -8 is a placeholder, left-align the output, and output length is 8
datefmt='%Y-%m-%d %H:%M:%S', # 时间输出的格式 datefmt='%Y-%m-%d %H:%M:%S', # Time output format
handlers=[logging.NullHandler()], handlers=[logging.NullHandler()],
) )

View File

@@ -7,7 +7,7 @@ from .. import note
@note.note_class('ClassicNotes', 1) @note.note_class('ClassicNotes', 1)
class ClassicNotes(note.LaunchNote): class ClassicNotes(note.LaunchNote):
"""经典启动信息""" """Classic launch information"""
async def need_show(self) -> bool: async def need_show(self) -> bool:
return True return True

View File

@@ -9,7 +9,7 @@ from .. import note
@note.note_class('SelectionModeOnWindows', 2) @note.note_class('SelectionModeOnWindows', 2)
class SelectionModeOnWindows(note.LaunchNote): class SelectionModeOnWindows(note.LaunchNote):
"""Windows 上的选择模式提示信息""" """Selection mode prompt information on Windows"""
async def need_show(self) -> bool: async def need_show(self) -> bool:
return os.name == 'nt' return os.name == 'nt'
@@ -19,3 +19,8 @@ class SelectionModeOnWindows(note.LaunchNote):
"""您正在使用 Windows 系统,若窗口左上角显示处于”选择“模式,程序将被暂停运行,此时请右键窗口中空白区域退出选择模式。""", """您正在使用 Windows 系统,若窗口左上角显示处于”选择“模式,程序将被暂停运行,此时请右键窗口中空白区域退出选择模式。""",
logging.INFO, logging.INFO,
) )
yield (
"""You are using Windows system, if the top left corner of the window displays "Selection" mode, the program will be paused running, please right-click on the blank area in the window to exit the selection mode.""",
logging.INFO,
)

View File

@@ -24,10 +24,10 @@ from .. import taskmgr
@stage.stage_class('BuildAppStage') @stage.stage_class('BuildAppStage')
class BuildAppStage(stage.BootingStage): class BuildAppStage(stage.BootingStage):
"""构建应用阶段""" """Build LangBot application"""
async def run(self, ap: app.Application): async def run(self, ap: app.Application):
"""构建app对象的各个组件对象并初始化""" """Build LangBot application"""
ap.task_mgr = taskmgr.AsyncTaskManager(ap) ap.task_mgr = taskmgr.AsyncTaskManager(ap)
discover = discover_engine.ComponentDiscoveryEngine(ap) discover = discover_engine.ComponentDiscoveryEngine(ap)
@@ -42,7 +42,7 @@ class BuildAppStage(stage.BootingStage):
await ver_mgr.initialize() await ver_mgr.initialize()
ap.ver_mgr = ver_mgr ap.ver_mgr = ver_mgr
# 发送公告 # Send announcement
ann_mgr = announce.AnnouncementManager(ap) ann_mgr = announce.AnnouncementManager(ap)
ap.ann_mgr = ann_mgr ap.ann_mgr = ann_mgr

View File

@@ -7,10 +7,10 @@ from .. import stage, app
@stage.stage_class('GenKeysStage') @stage.stage_class('GenKeysStage')
class GenKeysStage(stage.BootingStage): class GenKeysStage(stage.BootingStage):
"""生成密钥阶段""" """Generate keys stage"""
async def run(self, ap: app.Application): async def run(self, ap: app.Application):
"""启动""" """Generate keys"""
if not ap.instance_config.data['system']['jwt']['secret']: if not ap.instance_config.data['system']['jwt']['secret']:
ap.instance_config.data['system']['jwt']['secret'] = secrets.token_hex(16) ap.instance_config.data['system']['jwt']['secret'] = secrets.token_hex(16)

View File

@@ -8,10 +8,10 @@ from ..bootutils import config
@stage.stage_class('LoadConfigStage') @stage.stage_class('LoadConfigStage')
class LoadConfigStage(stage.BootingStage): class LoadConfigStage(stage.BootingStage):
"""加载配置文件阶段""" """Load config file stage"""
async def run(self, ap: app.Application): async def run(self, ap: app.Application):
"""启动""" """Load config file"""
# ======= deprecated ======= # ======= deprecated =======
if os.path.exists('data/config/command.json'): if os.path.exists('data/config/command.json'):

View File

@@ -11,10 +11,13 @@ importutil.import_modules_in_pkg(migrations)
@stage.stage_class('MigrationStage') @stage.stage_class('MigrationStage')
class MigrationStage(stage.BootingStage): class MigrationStage(stage.BootingStage):
"""迁移阶段""" """Migration stage
These migrations are legacy, only performed in version 3.x
"""
async def run(self, ap: app.Application): async def run(self, ap: app.Application):
"""启动""" """Run migration"""
if any( if any(
[ [
@@ -29,7 +32,7 @@ class MigrationStage(stage.BootingStage):
migrations = migration.preregistered_migrations migrations = migration.preregistered_migrations
# 按照迁移号排序 # Sort by migration number
migrations.sort(key=lambda x: x.number) migrations.sort(key=lambda x: x.number)
for migration_cls in migrations: for migration_cls in migrations:
@@ -37,4 +40,4 @@ class MigrationStage(stage.BootingStage):
if await migration_instance.need_migrate(): if await migration_instance.need_migrate():
await migration_instance.run() await migration_instance.run()
print(f'已执行迁移 {migration_instance.name}') print(f'Migration {migration_instance.name} executed')

View File

@@ -8,7 +8,7 @@ from ..bootutils import log
class PersistenceHandler(logging.Handler, object): class PersistenceHandler(logging.Handler, object):
""" """
保存日志到数据库 Save logs to database
""" """
ap: app.Application ap: app.Application
@@ -19,9 +19,9 @@ class PersistenceHandler(logging.Handler, object):
def emit(self, record): def emit(self, record):
""" """
emit函数为自定义handler类时必重写的函数这里可以根据需要对日志消息做一些处理比如发送日志到服务器 emit function is a required function for custom handler classes, here you can process the log messages as needed, such as sending logs to the server
发出记录(Emit a record) Emit a record
""" """
try: try:
msg = self.format(record) msg = self.format(record)
@@ -34,10 +34,10 @@ class PersistenceHandler(logging.Handler, object):
@stage.stage_class('SetupLoggerStage') @stage.stage_class('SetupLoggerStage')
class SetupLoggerStage(stage.BootingStage): class SetupLoggerStage(stage.BootingStage):
"""设置日志器阶段""" """Setup logger stage"""
async def run(self, ap: app.Application): async def run(self, ap: app.Application):
"""启动""" """Setup logger"""
persistence_handler = PersistenceHandler('LoggerHandler', ap) persistence_handler = PersistenceHandler('LoggerHandler', ap)
extra_handlers = [] extra_handlers = []

View File

@@ -12,10 +12,10 @@ importutil.import_modules_in_pkg(notes)
@stage.stage_class('ShowNotesStage') @stage.stage_class('ShowNotesStage')
class ShowNotesStage(stage.BootingStage): class ShowNotesStage(stage.BootingStage):
"""显示启动信息阶段""" """Show notes stage"""
async def run(self, ap: app.Application): async def run(self, ap: app.Application):
# 排序 # Sort
note.preregistered_notes.sort(key=lambda x: x.number) note.preregistered_notes.sort(key=lambda x: x.number)
for note_cls in note.preregistered_notes: for note_cls in note.preregistered_notes: