style: introduce ruff as linter and formatter (#1356)

* style: remove necessary imports

* style: fix F841

* style: fix F401

* style: fix F811

* style: fix E402

* style: fix E721

* style: fix E722

* style: fix E722

* style: fix F541

* style: ruff format

* style: all passed

* style: add ruff in deps

* style: more ignores in ruff.toml

* style: add pre-commit
This commit is contained in:
Junyan Qin (Chin)
2025-04-29 17:24:07 +08:00
committed by GitHub
parent 09e70d70e9
commit 209f16af76
240 changed files with 5307 additions and 4689 deletions

View File

@@ -2,9 +2,7 @@ from __future__ import annotations
import logging
import asyncio
import threading
import traceback
import enum
import sys
import os
@@ -29,7 +27,6 @@ from ..discover import engine as discover_engine
from ..utils import logcache, ip
from . import taskmgr
from . import entities as core_entities
from .bootutils import config
class Application:
@@ -123,33 +120,55 @@ class Application:
async def run(self):
try:
await self.plugin_mgr.initialize_plugins()
# 后续可能会允许动态重启其他任务
# 故为了防止程序在非 Ctrl-C 情况下退出,这里创建一个不会结束的协程
async def never_ending():
while True:
await asyncio.sleep(1)
self.task_mgr.create_task(self.platform_mgr.run(), name="platform-manager", scopes=[core_entities.LifecycleControlScope.APPLICATION, core_entities.LifecycleControlScope.PLATFORM])
self.task_mgr.create_task(self.ctrl.run(), name="query-controller", scopes=[core_entities.LifecycleControlScope.APPLICATION])
self.task_mgr.create_task(self.http_ctrl.run(), name="http-api-controller", scopes=[core_entities.LifecycleControlScope.APPLICATION])
self.task_mgr.create_task(never_ending(), name="never-ending-task", scopes=[core_entities.LifecycleControlScope.APPLICATION])
self.task_mgr.create_task(
self.platform_mgr.run(),
name='platform-manager',
scopes=[
core_entities.LifecycleControlScope.APPLICATION,
core_entities.LifecycleControlScope.PLATFORM,
],
)
self.task_mgr.create_task(
self.ctrl.run(),
name='query-controller',
scopes=[core_entities.LifecycleControlScope.APPLICATION],
)
self.task_mgr.create_task(
self.http_ctrl.run(),
name='http-api-controller',
scopes=[core_entities.LifecycleControlScope.APPLICATION],
)
self.task_mgr.create_task(
never_ending(),
name='never-ending-task',
scopes=[core_entities.LifecycleControlScope.APPLICATION],
)
await self.print_web_access_info()
await self.task_mgr.wait_all()
except asyncio.CancelledError:
pass
except Exception as e:
self.logger.error(f"应用运行致命异常: {e}")
self.logger.debug(f"Traceback: {traceback.format_exc()}")
self.logger.error(f'应用运行致命异常: {e}')
self.logger.debug(f'Traceback: {traceback.format_exc()}')
async def print_web_access_info(self):
"""打印访问 webui 的提示"""
if not os.path.exists(os.path.join(".", "web/out")):
self.logger.warning("WebUI 文件缺失请根据文档获取https://docs.langbot.app/webui/intro.html")
if not os.path.exists(os.path.join('.', 'web/out')):
self.logger.warning(
'WebUI 文件缺失请根据文档获取https://docs.langbot.app/webui/intro.html'
)
return
host_ip = "127.0.0.1"
host_ip = '127.0.0.1'
public_ip = await ip.get_myip()
@@ -170,7 +189,7 @@ class Application:
🤯 WebUI 仍处于 Beta 测试阶段,如有问题或建议请反馈到 https://github.com/RockChinQ/LangBot/issues
=======================================
""".strip()
for line in tips.split("\n"):
for line in tips.split('\n'):
self.logger.info(line)
async def reload(
@@ -179,21 +198,28 @@ class Application:
):
match scope:
case core_entities.LifecycleControlScope.PLATFORM.value:
self.logger.info("执行热重载 scope="+scope)
self.logger.info('执行热重载 scope=' + scope)
await self.platform_mgr.shutdown()
self.platform_mgr = im_mgr.PlatformManager(self)
await self.platform_mgr.initialize()
self.task_mgr.create_task(self.platform_mgr.run(), name="platform-manager", scopes=[core_entities.LifecycleControlScope.APPLICATION, core_entities.LifecycleControlScope.PLATFORM])
self.task_mgr.create_task(
self.platform_mgr.run(),
name='platform-manager',
scopes=[
core_entities.LifecycleControlScope.APPLICATION,
core_entities.LifecycleControlScope.PLATFORM,
],
)
case core_entities.LifecycleControlScope.PLUGIN.value:
self.logger.info("执行热重载 scope="+scope)
self.logger.info('执行热重载 scope=' + scope)
await self.plugin_mgr.destroy_plugins()
# 删除 sys.module 中所有的 plugins/* 下的模块
for mod in list(sys.modules.keys()):
if mod.startswith("plugins."):
if mod.startswith('plugins.'):
del sys.modules[mod]
self.plugin_mgr = plugin_mgr.PluginManager(self)
@@ -204,7 +230,7 @@ class Application:
await self.plugin_mgr.load_plugins()
await self.plugin_mgr.initialize_plugins()
case core_entities.LifecycleControlScope.PROVIDER.value:
self.logger.info("执行热重载 scope="+scope)
self.logger.info('执行热重载 scope=' + scope)
await self.tool_mgr.shutdown()
@@ -220,4 +246,4 @@ class Application:
await llm_tool_mgr_inst.initialize()
self.tool_mgr = llm_tool_mgr_inst
case _:
pass
pass

View File

@@ -7,29 +7,30 @@ import os
from . import app
from ..audit import identifier
from . import stage
from ..utils import constants
from ..utils import constants, importutil
# 引入启动阶段实现以便注册
from .stages import load_config, setup_logger, build_app, migrate, show_notes, genkeys
from . import stages
importutil.import_modules_in_pkg(stages)
stage_order = [
"LoadConfigStage",
"MigrationStage",
"GenKeysStage",
"SetupLoggerStage",
"BuildAppStage",
"ShowNotesStage"
'LoadConfigStage',
'MigrationStage',
'GenKeysStage',
'SetupLoggerStage',
'BuildAppStage',
'ShowNotesStage',
]
async def make_app(loop: asyncio.AbstractEventLoop) -> app.Application:
# 生成标识符
identifier.init()
# 确定是否为调试模式
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
ap = app.Application()
@@ -50,21 +51,17 @@ async def make_app(loop: asyncio.AbstractEventLoop) -> app.Application:
async def main(loop: asyncio.AbstractEventLoop):
try:
# 挂系统信号处理
import signal
ap: app.Application
def signal_handler(sig, frame):
print("[Signal] 程序退出.")
print('[Signal] 程序退出.')
# ap.shutdown()
os._exit(0)
signal.signal(signal.SIGINT, signal_handler)
app_inst = await make_app(loop)
ap = app_inst
await app_inst.run()
except Exception as e:
except Exception:
traceback.print_exc()

View File

@@ -1,11 +1,9 @@
from __future__ import annotations
import json
from ...config import manager as config_mgr
from ...config.impls import pymodule
load_python_module_config = config_mgr.load_python_module_config
load_json_config = config_mgr.load_json_config
load_yaml_config = config_mgr.load_yaml_config
load_yaml_config = config_mgr.load_yaml_config

View File

@@ -5,39 +5,39 @@ from ...utils import pkgmgr
# 检查依赖,防止用户未安装
# 左边为引入名称,右边为依赖名称
required_deps = {
"requests": "requests",
"openai": "openai",
"anthropic": "anthropic",
"colorlog": "colorlog",
"aiocqhttp": "aiocqhttp",
"botpy": "qq-botpy-rc",
"PIL": "pillow",
"nakuru": "nakuru-project-idk",
"tiktoken": "tiktoken",
"yaml": "pyyaml",
"aiohttp": "aiohttp",
"psutil": "psutil",
"async_lru": "async-lru",
"ollama": "ollama",
"quart": "quart",
"quart_cors": "quart-cors",
"sqlalchemy": "sqlalchemy[asyncio]",
"aiosqlite": "aiosqlite",
"aiofiles": "aiofiles",
"aioshutil": "aioshutil",
"argon2": "argon2-cffi",
"jwt": "pyjwt",
"Crypto": "pycryptodome",
"lark_oapi": "lark-oapi",
"discord": "discord.py",
"cryptography": "cryptography",
"gewechat_client": "gewechat-client",
"dingtalk_stream": "dingtalk_stream",
"dashscope": "dashscope",
"telegram": "python-telegram-bot",
"certifi": "certifi",
"mcp": "mcp",
"sqlmodel": "sqlmodel",
'requests': 'requests',
'openai': 'openai',
'anthropic': 'anthropic',
'colorlog': 'colorlog',
'aiocqhttp': 'aiocqhttp',
'botpy': 'qq-botpy-rc',
'PIL': 'pillow',
'nakuru': 'nakuru-project-idk',
'tiktoken': 'tiktoken',
'yaml': 'pyyaml',
'aiohttp': 'aiohttp',
'psutil': 'psutil',
'async_lru': 'async-lru',
'ollama': 'ollama',
'quart': 'quart',
'quart_cors': 'quart-cors',
'sqlalchemy': 'sqlalchemy[asyncio]',
'aiosqlite': 'aiosqlite',
'aiofiles': 'aiofiles',
'aioshutil': 'aioshutil',
'argon2': 'argon2-cffi',
'jwt': 'pyjwt',
'Crypto': 'pycryptodome',
'lark_oapi': 'lark-oapi',
'discord': 'discord.py',
'cryptography': 'cryptography',
'gewechat_client': 'gewechat-client',
'dingtalk_stream': 'dingtalk_stream',
'dashscope': 'dashscope',
'telegram': 'python-telegram-bot',
'certifi': 'certifi',
'mcp': 'mcp',
'sqlmodel': 'sqlmodel',
}
@@ -52,20 +52,25 @@ async def check_deps() -> list[str]:
missing_deps.append(dep)
return missing_deps
async def install_deps(deps: list[str]):
global required_deps
for dep in deps:
pip.main(["install", required_deps[dep]])
pip.main(['install', required_deps[dep]])
async def precheck_plugin_deps():
print('[Startup] Prechecking plugin dependencies...')
# 只有在plugins目录存在时才执行插件依赖安装
if os.path.exists("plugins"):
for dir in os.listdir("plugins"):
subdir = os.path.join("plugins", dir)
if os.path.exists('plugins'):
for dir in os.listdir('plugins'):
subdir = os.path.join('plugins', dir)
if not os.path.isdir(subdir):
continue
if 'requirements.txt' in os.listdir(subdir):
pkgmgr.install_requirements(os.path.join(subdir, 'requirements.txt'), extra_params=['-q', '-q', '-q'])
pkgmgr.install_requirements(
os.path.join(subdir, 'requirements.txt'),
extra_params=['-q', '-q', '-q'],
)

View File

@@ -2,23 +2,23 @@ from __future__ import annotations
import os
import shutil
import sys
required_files = {
"plugins/__init__.py": "templates/__init__.py",
"data/config.yaml": "templates/config.yaml",
'plugins/__init__.py': 'templates/__init__.py',
'data/config.yaml': 'templates/config.yaml',
}
required_paths = [
"temp",
"data",
"data/metadata",
"data/logs",
"data/labels",
"plugins"
'temp',
'data',
'data/metadata',
'data/logs',
'data/labels',
'plugins',
]
async def generate_files() -> list[str]:
global required_files, required_paths

View File

@@ -1,5 +1,4 @@
import logging
import os
import sys
import time
@@ -9,11 +8,11 @@ from ...utils import constants
log_colors_config = {
"DEBUG": "green", # cyan white
"INFO": "white",
"WARNING": "yellow",
"ERROR": "red",
"CRITICAL": "cyan",
'DEBUG': 'green', # cyan white
'INFO': 'white',
'WARNING': 'yellow',
'ERROR': 'red',
'CRITICAL': 'cyan',
}
@@ -27,26 +26,31 @@ async def init_logging(extra_handlers: list[logging.Handler] = None) -> logging.
if constants.debug_mode:
level = logging.DEBUG
log_file_name = "data/logs/langbot-%s.log" % time.strftime(
"%Y-%m-%d", time.localtime()
log_file_name = 'data/logs/langbot-%s.log' % time.strftime(
'%Y-%m-%d', time.localtime()
)
qcg_logger = logging.getLogger("langbot")
qcg_logger = logging.getLogger('langbot')
qcg_logger.setLevel(level)
color_formatter = colorlog.ColoredFormatter(
fmt="%(log_color)s[%(asctime)s.%(msecs)03d] %(filename)s (%(lineno)d) - [%(levelname)s] : %(message)s",
datefmt="%m-%d %H:%M:%S",
fmt='%(log_color)s[%(asctime)s.%(msecs)03d] %(filename)s (%(lineno)d) - [%(levelname)s] : %(message)s',
datefmt='%m-%d %H:%M:%S',
log_colors=log_colors_config,
)
stream_handler = logging.StreamHandler(sys.stdout)
# stream_handler.setLevel(level)
# stream_handler.setFormatter(color_formatter)
stream_handler.stream = open(sys.stdout.fileno(), mode='w', encoding='utf-8', buffering=1)
stream_handler.stream = open(
sys.stdout.fileno(), mode='w', encoding='utf-8', buffering=1
)
log_handlers: list[logging.Handler] = [stream_handler, logging.FileHandler(log_file_name, encoding='utf-8')]
log_handlers: list[logging.Handler] = [
stream_handler,
logging.FileHandler(log_file_name, encoding='utf-8'),
]
log_handlers += extra_handlers if extra_handlers is not None else []
for handler in log_handlers:
@@ -54,13 +58,13 @@ async def init_logging(extra_handlers: list[logging.Handler] = None) -> logging.
handler.setFormatter(color_formatter)
qcg_logger.addHandler(handler)
qcg_logger.debug("日志初始化完成,日志级别:%s" % level)
qcg_logger.debug('日志初始化完成,日志级别:%s' % level)
logging.basicConfig(
level=logging.CRITICAL, # 设置日志输出格式
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',
# 日志输出的格式
# -8表示占位符让输出左对齐输出长度都为8位
datefmt="%Y-%m-%d %H:%M:%S", # 时间输出的格式
datefmt='%Y-%m-%d %H:%M:%S', # 时间输出的格式
handlers=[logging.NullHandler()],
)

View File

@@ -8,21 +8,18 @@ import asyncio
import pydantic.v1 as pydantic
from ..provider import entities as llm_entities
from ..provider.modelmgr import entities, modelmgr, requester
from ..provider.modelmgr import requester
from ..provider.tools import entities as tools_entities
from ..platform import adapter as msadapter
from ..platform.types import message as platform_message
from ..platform.types import events as platform_events
from ..platform.types import entities as platform_entities
class LifecycleControlScope(enum.Enum):
APPLICATION = "application"
PLATFORM = "platform"
PLUGIN = "plugin"
PROVIDER = "provider"
APPLICATION = 'application'
PLATFORM = 'platform'
PLUGIN = 'plugin'
PROVIDER = 'provider'
class LauncherTypes(enum.Enum):
@@ -89,14 +86,17 @@ class Query(pydantic.BaseModel):
use_funcs: typing.Optional[list[tools_entities.LLMFunction]] = None
"""使用的函数,由前置处理器阶段设置"""
resp_messages: typing.Optional[list[llm_entities.Message]] | typing.Optional[list[platform_message.MessageChain]] = []
resp_messages: (
typing.Optional[list[llm_entities.Message]]
| typing.Optional[list[platform_message.MessageChain]]
) = []
"""由Process阶段生成的回复消息对象列表"""
resp_message_chain: typing.Optional[list[platform_message.MessageChain]] = None
"""回复消息链从resp_messages包装而得"""
# ======= 内部保留 =======
current_stage: "pkg.pipeline.pipelinemgr.StageInstContainer" = None
current_stage = None # pkg.pipeline.pipelinemgr.StageInstContainer
"""当前所处阶段"""
class Config:
@@ -109,13 +109,13 @@ class Query(pydantic.BaseModel):
if self.variables is None:
self.variables = {}
self.variables[key] = value
def get_variable(self, key: str) -> typing.Any:
"""获取变量"""
if self.variables is None:
return None
return self.variables.get(key)
def get_variables(self) -> dict[str, typing.Any]:
"""获取所有变量"""
if self.variables is None:
@@ -130,9 +130,13 @@ class Conversation(pydantic.BaseModel):
messages: list[llm_entities.Message]
create_time: typing.Optional[datetime.datetime] = pydantic.Field(default_factory=datetime.datetime.now)
create_time: typing.Optional[datetime.datetime] = pydantic.Field(
default_factory=datetime.datetime.now
)
update_time: typing.Optional[datetime.datetime] = pydantic.Field(default_factory=datetime.datetime.now)
update_time: typing.Optional[datetime.datetime] = pydantic.Field(
default_factory=datetime.datetime.now
)
use_llm_model: requester.RuntimeLLMModel
@@ -147,6 +151,7 @@ class Conversation(pydantic.BaseModel):
class Session(pydantic.BaseModel):
"""会话,一个 Session 对应一个 {launcher_type.value}_{launcher_id}"""
launcher_type: LauncherTypes
launcher_id: typing.Union[int, str]
@@ -157,11 +162,17 @@ class Session(pydantic.BaseModel):
using_conversation: typing.Optional[Conversation] = None
conversations: typing.Optional[list[Conversation]] = pydantic.Field(default_factory=list)
conversations: typing.Optional[list[Conversation]] = pydantic.Field(
default_factory=list
)
create_time: typing.Optional[datetime.datetime] = pydantic.Field(default_factory=datetime.datetime.now)
create_time: typing.Optional[datetime.datetime] = pydantic.Field(
default_factory=datetime.datetime.now
)
update_time: typing.Optional[datetime.datetime] = pydantic.Field(default_factory=datetime.datetime.now)
update_time: typing.Optional[datetime.datetime] = pydantic.Field(
default_factory=datetime.datetime.now
)
semaphore: typing.Optional[asyncio.Semaphore] = None
"""当前会话的信号量,用于限制并发"""

View File

@@ -9,21 +9,21 @@ from . import app
preregistered_migrations: list[typing.Type[Migration]] = []
"""当前阶段暂不支持扩展"""
def migration_class(name: str, number: int):
"""注册一个迁移
"""
"""注册一个迁移"""
def decorator(cls: typing.Type[Migration]) -> typing.Type[Migration]:
cls.name = name
cls.number = number
preregistered_migrations.append(cls)
return cls
return decorator
class Migration(abc.ABC):
"""一个版本的迁移
"""
"""一个版本的迁移"""
name: str
@@ -33,15 +33,13 @@ class Migration(abc.ABC):
def __init__(self, ap: app.Application):
self.ap = ap
@abc.abstractmethod
async def need_migrate(self) -> bool:
"""判断当前环境是否需要运行此迁移
"""
"""判断当前环境是否需要运行此迁移"""
pass
@abc.abstractmethod
async def run(self):
"""执行迁移
"""
"""执行迁移"""
pass

View File

@@ -1,26 +1,26 @@
from __future__ import annotations
import os
import sys
from .. import migration
@migration.migration_class("sensitive-word-migration", 1)
@migration.migration_class('sensitive-word-migration', 1)
class SensitiveWordMigration(migration.Migration):
"""敏感词迁移
"""
"""敏感词迁移"""
async def need_migrate(self) -> bool:
"""判断当前环境是否需要运行此迁移
"""
return os.path.exists("data/config/sensitive-words.json") and not os.path.exists("data/metadata/sensitive-words.json")
"""判断当前环境是否需要运行此迁移"""
return os.path.exists(
'data/config/sensitive-words.json'
) and not os.path.exists('data/metadata/sensitive-words.json')
async def run(self):
"""执行迁移
"""
"""执行迁移"""
# 移动文件
os.rename("data/config/sensitive-words.json", "data/metadata/sensitive-words.json")
os.rename(
'data/config/sensitive-words.json', 'data/metadata/sensitive-words.json'
)
# 重新加载配置
await self.ap.sensitive_meta.load_config()

View File

@@ -3,19 +3,16 @@ from __future__ import annotations
from .. import migration
@migration.migration_class("openai-config-migration", 2)
@migration.migration_class('openai-config-migration', 2)
class OpenAIConfigMigration(migration.Migration):
"""OpenAI配置迁移
"""
"""OpenAI配置迁移"""
async def need_migrate(self) -> bool:
"""判断当前环境是否需要运行此迁移
"""
"""判断当前环境是否需要运行此迁移"""
return 'openai-config' in self.ap.provider_cfg.data
async def run(self):
"""执行迁移
"""
"""执行迁移"""
old_openai_config = self.ap.provider_cfg.data['openai-config'].copy()
if 'keys' not in self.ap.provider_cfg.data:
@@ -26,7 +23,9 @@ class OpenAIConfigMigration(migration.Migration):
self.ap.provider_cfg.data['keys']['openai'] = old_openai_config['api-keys']
self.ap.provider_cfg.data['model'] = old_openai_config['chat-completions-params']['model']
self.ap.provider_cfg.data['model'] = old_openai_config[
'chat-completions-params'
]['model']
del old_openai_config['chat-completions-params']['model']
@@ -35,7 +34,7 @@ class OpenAIConfigMigration(migration.Migration):
if 'openai-chat-completions' not in self.ap.provider_cfg.data['requester']:
self.ap.provider_cfg.data['requester']['openai-chat-completions'] = {}
self.ap.provider_cfg.data['requester']['openai-chat-completions'] = {
'base-url': old_openai_config['base_url'],
'args': old_openai_config['chat-completions-params'],
@@ -44,4 +43,4 @@ class OpenAIConfigMigration(migration.Migration):
del self.ap.provider_cfg.data['openai-config']
await self.ap.provider_cfg.dump_config()
await self.ap.provider_cfg.dump_config()

View File

@@ -3,26 +3,23 @@ from __future__ import annotations
from .. import migration
@migration.migration_class("anthropic-requester-config-completion", 3)
@migration.migration_class('anthropic-requester-config-completion', 3)
class AnthropicRequesterConfigCompletionMigration(migration.Migration):
"""OpenAI配置迁移
"""
"""OpenAI配置迁移"""
async def need_migrate(self) -> bool:
"""判断当前环境是否需要运行此迁移
"""
return 'anthropic-messages' not in self.ap.provider_cfg.data['requester'] \
"""判断当前环境是否需要运行此迁移"""
return (
'anthropic-messages' not in self.ap.provider_cfg.data['requester']
or 'anthropic' not in self.ap.provider_cfg.data['keys']
)
async def run(self):
"""执行迁移
"""
"""执行迁移"""
if 'anthropic-messages' not in self.ap.provider_cfg.data['requester']:
self.ap.provider_cfg.data['requester']['anthropic-messages'] = {
'base-url': 'https://api.anthropic.com',
'args': {
'max_tokens': 1024
},
'args': {'max_tokens': 1024},
'timeout': 120,
}

View File

@@ -3,20 +3,19 @@ from __future__ import annotations
from .. import migration
@migration.migration_class("moonshot-config-completion", 4)
@migration.migration_class('moonshot-config-completion', 4)
class MoonshotConfigCompletionMigration(migration.Migration):
"""OpenAI配置迁移
"""
"""OpenAI配置迁移"""
async def need_migrate(self) -> bool:
"""判断当前环境是否需要运行此迁移
"""
return 'moonshot-chat-completions' not in self.ap.provider_cfg.data['requester'] \
"""判断当前环境是否需要运行此迁移"""
return (
'moonshot-chat-completions' not in self.ap.provider_cfg.data['requester']
or 'moonshot' not in self.ap.provider_cfg.data['keys']
)
async def run(self):
"""执行迁移
"""
"""执行迁移"""
if 'moonshot-chat-completions' not in self.ap.provider_cfg.data['requester']:
self.ap.provider_cfg.data['requester']['moonshot-chat-completions'] = {
'base-url': 'https://api.moonshot.cn/v1',

View File

@@ -3,20 +3,19 @@ from __future__ import annotations
from .. import migration
@migration.migration_class("deepseek-config-completion", 5)
@migration.migration_class('deepseek-config-completion', 5)
class DeepseekConfigCompletionMigration(migration.Migration):
"""OpenAI配置迁移
"""
"""OpenAI配置迁移"""
async def need_migrate(self) -> bool:
"""判断当前环境是否需要运行此迁移
"""
return 'deepseek-chat-completions' not in self.ap.provider_cfg.data['requester'] \
"""判断当前环境是否需要运行此迁移"""
return (
'deepseek-chat-completions' not in self.ap.provider_cfg.data['requester']
or 'deepseek' not in self.ap.provider_cfg.data['keys']
)
async def run(self):
"""执行迁移
"""
"""执行迁移"""
if 'deepseek-chat-completions' not in self.ap.provider_cfg.data['requester']:
self.ap.provider_cfg.data['requester']['deepseek-chat-completions'] = {
'base-url': 'https://api.deepseek.com',
@@ -27,4 +26,4 @@ class DeepseekConfigCompletionMigration(migration.Migration):
if 'deepseek' not in self.ap.provider_cfg.data['keys']:
self.ap.provider_cfg.data['keys']['deepseek'] = []
await self.ap.provider_cfg.dump_config()
await self.ap.provider_cfg.dump_config()

View File

@@ -3,17 +3,17 @@ from __future__ import annotations
from .. import migration
@migration.migration_class("vision-config", 6)
@migration.migration_class('vision-config', 6)
class VisionConfigMigration(migration.Migration):
"""迁移"""
async def need_migrate(self) -> bool:
"""判断当前环境是否需要运行此迁移"""
return "enable-vision" not in self.ap.provider_cfg.data
return 'enable-vision' not in self.ap.provider_cfg.data
async def run(self):
"""执行迁移"""
if "enable-vision" not in self.ap.provider_cfg.data:
self.ap.provider_cfg.data["enable-vision"] = False
if 'enable-vision' not in self.ap.provider_cfg.data:
self.ap.provider_cfg.data['enable-vision'] = False
await self.ap.provider_cfg.dump_config()

View File

@@ -3,18 +3,20 @@ from __future__ import annotations
from .. import migration
@migration.migration_class("qcg-center-url-config", 7)
@migration.migration_class('qcg-center-url-config', 7)
class QCGCenterURLConfigMigration(migration.Migration):
"""迁移"""
async def need_migrate(self) -> bool:
"""判断当前环境是否需要运行此迁移"""
return "qcg-center-url" not in self.ap.system_cfg.data
return 'qcg-center-url' not in self.ap.system_cfg.data
async def run(self):
"""执行迁移"""
if "qcg-center-url" not in self.ap.system_cfg.data:
self.ap.system_cfg.data["qcg-center-url"] = "https://api.qchatgpt.rockchin.top/api/v2"
if 'qcg-center-url' not in self.ap.system_cfg.data:
self.ap.system_cfg.data['qcg-center-url'] = (
'https://api.qchatgpt.rockchin.top/api/v2'
)
await self.ap.system_cfg.dump_config()

View File

@@ -3,27 +3,27 @@ from __future__ import annotations
from .. import migration
@migration.migration_class("ad-fixwin-cfg-migration", 8)
@migration.migration_class('ad-fixwin-cfg-migration', 8)
class AdFixwinConfigMigration(migration.Migration):
"""迁移"""
async def need_migrate(self) -> bool:
"""判断当前环境是否需要运行此迁移"""
return isinstance(
self.ap.pipeline_cfg.data["rate-limit"]["fixwin"]["default"],
int
self.ap.pipeline_cfg.data['rate-limit']['fixwin']['default'], int
)
async def run(self):
"""执行迁移"""
for session_name in self.ap.pipeline_cfg.data["rate-limit"]["fixwin"]:
for session_name in self.ap.pipeline_cfg.data['rate-limit']['fixwin']:
temp_dict = {
"window-size": 60,
"limit": self.ap.pipeline_cfg.data["rate-limit"]["fixwin"][session_name]
'window-size': 60,
'limit': self.ap.pipeline_cfg.data['rate-limit']['fixwin'][
session_name
],
}
self.ap.pipeline_cfg.data["rate-limit"]["fixwin"][session_name] = temp_dict
await self.ap.pipeline_cfg.dump_config()
self.ap.pipeline_cfg.data['rate-limit']['fixwin'][session_name] = temp_dict
await self.ap.pipeline_cfg.dump_config()

View File

@@ -3,7 +3,7 @@ from __future__ import annotations
from .. import migration
@migration.migration_class("msg-truncator-cfg-migration", 9)
@migration.migration_class('msg-truncator-cfg-migration', 9)
class MsgTruncatorConfigMigration(migration.Migration):
"""迁移"""
@@ -13,12 +13,10 @@ class MsgTruncatorConfigMigration(migration.Migration):
async def run(self):
"""执行迁移"""
self.ap.pipeline_cfg.data['msg-truncate'] = {
'method': 'round',
'round': {
'max-round': 10
}
'round': {'max-round': 10},
}
await self.ap.pipeline_cfg.dump_config()

View File

@@ -3,7 +3,7 @@ from __future__ import annotations
from .. import migration
@migration.migration_class("ollama-requester-config", 10)
@migration.migration_class('ollama-requester-config', 10)
class MsgTruncatorConfigMigration(migration.Migration):
"""迁移"""
@@ -13,11 +13,11 @@ class MsgTruncatorConfigMigration(migration.Migration):
async def run(self):
"""执行迁移"""
self.ap.provider_cfg.data['requester']['ollama-chat'] = {
"base-url": "http://127.0.0.1:11434",
"args": {},
"timeout": 600
'base-url': 'http://127.0.0.1:11434',
'args': {},
'timeout': 600,
}
await self.ap.provider_cfg.dump_config()

View File

@@ -3,7 +3,7 @@ from __future__ import annotations
from .. import migration
@migration.migration_class("command-prefix-config", 11)
@migration.migration_class('command-prefix-config', 11)
class CommandPrefixConfigMigration(migration.Migration):
"""迁移"""
@@ -13,9 +13,7 @@ class CommandPrefixConfigMigration(migration.Migration):
async def run(self):
"""执行迁移"""
self.ap.command_cfg.data['command-prefix'] = [
"!", ""
]
self.ap.command_cfg.data['command-prefix'] = ['!', '']
await self.ap.command_cfg.dump_config()

View File

@@ -3,7 +3,7 @@ from __future__ import annotations
from .. import migration
@migration.migration_class("runner-config", 12)
@migration.migration_class('runner-config', 12)
class RunnerConfigMigration(migration.Migration):
"""迁移"""
@@ -13,7 +13,7 @@ class RunnerConfigMigration(migration.Migration):
async def run(self):
"""执行迁移"""
self.ap.provider_cfg.data['runner'] = 'local-agent'
await self.ap.provider_cfg.dump_config()

View File

@@ -3,29 +3,30 @@ from __future__ import annotations
from .. import migration
@migration.migration_class("http-api-config", 13)
@migration.migration_class('http-api-config', 13)
class HttpApiConfigMigration(migration.Migration):
"""迁移"""
async def need_migrate(self) -> bool:
"""判断当前环境是否需要运行此迁移"""
return 'http-api' not in self.ap.system_cfg.data or "persistence" not in self.ap.system_cfg.data
return (
'http-api' not in self.ap.system_cfg.data
or 'persistence' not in self.ap.system_cfg.data
)
async def run(self):
"""执行迁移"""
self.ap.system_cfg.data['http-api'] = {
"enable": True,
"host": "0.0.0.0",
"port": 5300,
"jwt-expire": 604800
'enable': True,
'host': '0.0.0.0',
'port': 5300,
'jwt-expire': 604800,
}
self.ap.system_cfg.data['persistence'] = {
"sqlite": {
"path": "data/persistence.db"
},
"use": "sqlite"
'sqlite': {'path': 'data/persistence.db'},
'use': 'sqlite',
}
await self.ap.system_cfg.dump_config()

View File

@@ -3,20 +3,20 @@ from __future__ import annotations
from .. import migration
@migration.migration_class("force-delay-config", 14)
@migration.migration_class('force-delay-config', 14)
class ForceDelayConfigMigration(migration.Migration):
"""迁移"""
async def need_migrate(self) -> bool:
"""判断当前环境是否需要运行此迁移"""
return type(self.ap.platform_cfg.data['force-delay']) == list
return isinstance(self.ap.platform_cfg.data['force-delay'], list)
async def run(self):
"""执行迁移"""
self.ap.platform_cfg.data['force-delay'] = {
"min": self.ap.platform_cfg.data['force-delay'][0],
"max": self.ap.platform_cfg.data['force-delay'][1]
'min': self.ap.platform_cfg.data['force-delay'][0],
'max': self.ap.platform_cfg.data['force-delay'][1],
}
await self.ap.platform_cfg.dump_config()

View File

@@ -3,24 +3,25 @@ from __future__ import annotations
from .. import migration
@migration.migration_class("gitee-ai-config", 15)
@migration.migration_class('gitee-ai-config', 15)
class GiteeAIConfigMigration(migration.Migration):
"""迁移"""
async def need_migrate(self) -> bool:
"""判断当前环境是否需要运行此迁移"""
return 'gitee-ai-chat-completions' not in self.ap.provider_cfg.data['requester'] or 'gitee-ai' not in self.ap.provider_cfg.data['keys']
return (
'gitee-ai-chat-completions' not in self.ap.provider_cfg.data['requester']
or 'gitee-ai' not in self.ap.provider_cfg.data['keys']
)
async def run(self):
"""执行迁移"""
self.ap.provider_cfg.data['requester']['gitee-ai-chat-completions'] = {
"base-url": "https://ai.gitee.com/v1",
"args": {},
"timeout": 120
'base-url': 'https://ai.gitee.com/v1',
'args': {},
'timeout': 120,
}
self.ap.provider_cfg.data['keys']['gitee-ai'] = [
"XXXXX"
]
self.ap.provider_cfg.data['keys']['gitee-ai'] = ['XXXXX']
await self.ap.provider_cfg.dump_config()

View File

@@ -3,7 +3,7 @@ from __future__ import annotations
from .. import migration
@migration.migration_class("dify-service-api-config", 16)
@migration.migration_class('dify-service-api-config', 16)
class DifyServiceAPICfgMigration(migration.Migration):
"""迁移"""
@@ -14,15 +14,10 @@ class DifyServiceAPICfgMigration(migration.Migration):
async def run(self):
"""执行迁移"""
self.ap.provider_cfg.data['dify-service-api'] = {
"base-url": "https://api.dify.ai/v1",
"app-type": "chat",
"chat": {
"api-key": "app-1234567890"
},
"workflow": {
"api-key": "app-1234567890",
"output-key": "summary"
}
'base-url': 'https://api.dify.ai/v1',
'app-type': 'chat',
'chat': {'api-key': 'app-1234567890'},
'workflow': {'api-key': 'app-1234567890', 'output-key': 'summary'},
}
await self.ap.provider_cfg.dump_config()

View File

@@ -3,22 +3,26 @@ from __future__ import annotations
from .. import migration
@migration.migration_class("dify-api-timeout-params", 17)
@migration.migration_class('dify-api-timeout-params', 17)
class DifyAPITimeoutParamsMigration(migration.Migration):
"""迁移"""
async def need_migrate(self) -> bool:
"""判断当前环境是否需要运行此迁移"""
return 'timeout' not in self.ap.provider_cfg.data['dify-service-api']['chat'] or 'timeout' not in self.ap.provider_cfg.data['dify-service-api']['workflow'] \
return (
'timeout' not in self.ap.provider_cfg.data['dify-service-api']['chat']
or 'timeout'
not in self.ap.provider_cfg.data['dify-service-api']['workflow']
or 'agent' not in self.ap.provider_cfg.data['dify-service-api']
)
async def run(self):
"""执行迁移"""
self.ap.provider_cfg.data['dify-service-api']['chat']['timeout'] = 120
self.ap.provider_cfg.data['dify-service-api']['workflow']['timeout'] = 120
self.ap.provider_cfg.data['dify-service-api']['agent'] = {
"api-key": "app-1234567890",
"timeout": 120
'api-key': 'app-1234567890',
'timeout': 120,
}
await self.ap.provider_cfg.dump_config()

View File

@@ -3,7 +3,7 @@ from __future__ import annotations
from .. import migration
@migration.migration_class("xai-config", 18)
@migration.migration_class('xai-config', 18)
class XaiConfigMigration(migration.Migration):
"""迁移"""
@@ -14,12 +14,10 @@ class XaiConfigMigration(migration.Migration):
async def run(self):
"""执行迁移"""
self.ap.provider_cfg.data['requester']['xai-chat-completions'] = {
"base-url": "https://api.x.ai/v1",
"args": {},
"timeout": 120
'base-url': 'https://api.x.ai/v1',
'args': {},
'timeout': 120,
}
self.ap.provider_cfg.data['keys']['xai'] = [
"xai-1234567890"
]
self.ap.provider_cfg.data['keys']['xai'] = ['xai-1234567890']
await self.ap.provider_cfg.dump_config()

View File

@@ -3,7 +3,7 @@ from __future__ import annotations
from .. import migration
@migration.migration_class("zhipuai-config", 19)
@migration.migration_class('zhipuai-config', 19)
class ZhipuaiConfigMigration(migration.Migration):
"""迁移"""
@@ -14,12 +14,10 @@ class ZhipuaiConfigMigration(migration.Migration):
async def run(self):
"""执行迁移"""
self.ap.provider_cfg.data['requester']['zhipuai-chat-completions'] = {
"base-url": "https://open.bigmodel.cn/api/paas/v4",
"args": {},
"timeout": 120
'base-url': 'https://open.bigmodel.cn/api/paas/v4',
'args': {},
'timeout': 120,
}
self.ap.provider_cfg.data['keys']['zhipuai'] = [
"xxxxxxx"
]
self.ap.provider_cfg.data['keys']['zhipuai'] = ['xxxxxxx']
await self.ap.provider_cfg.dump_config()

View File

@@ -3,13 +3,13 @@ from __future__ import annotations
from .. import migration
@migration.migration_class("wecom-config", 20)
@migration.migration_class('wecom-config', 20)
class WecomConfigMigration(migration.Migration):
"""迁移"""
async def need_migrate(self) -> bool:
"""判断当前环境是否需要运行此迁移"""
# for adapter in self.ap.platform_cfg.data['platform-adapters']:
# if adapter['adapter'] == 'wecom':
# return False
@@ -19,16 +19,18 @@ class WecomConfigMigration(migration.Migration):
async def run(self):
"""执行迁移"""
self.ap.platform_cfg.data['platform-adapters'].append({
"adapter": "wecom",
"enable": False,
"host": "0.0.0.0",
"port": 2290,
"corpid": "",
"secret": "",
"token": "",
"EncodingAESKey": "",
"contacts_secret": ""
})
self.ap.platform_cfg.data['platform-adapters'].append(
{
'adapter': 'wecom',
'enable': False,
'host': '0.0.0.0',
'port': 2290,
'corpid': '',
'secret': '',
'token': '',
'EncodingAESKey': '',
'contacts_secret': '',
}
)
await self.ap.platform_cfg.dump_config()

View File

@@ -3,13 +3,13 @@ from __future__ import annotations
from .. import migration
@migration.migration_class("lark-config", 21)
@migration.migration_class('lark-config', 21)
class LarkConfigMigration(migration.Migration):
"""迁移"""
async def need_migrate(self) -> bool:
"""判断当前环境是否需要运行此迁移"""
# for adapter in self.ap.platform_cfg.data['platform-adapters']:
# if adapter['adapter'] == 'lark':
# return False
@@ -19,15 +19,17 @@ class LarkConfigMigration(migration.Migration):
async def run(self):
"""执行迁移"""
self.ap.platform_cfg.data['platform-adapters'].append({
"adapter": "lark",
"enable": False,
"app_id": "cli_abcdefgh",
"app_secret": "XXXXXXXXXX",
"bot_name": "LangBot",
"enable-webhook": False,
"port": 2285,
"encrypt-key": "xxxxxxxxx"
})
self.ap.platform_cfg.data['platform-adapters'].append(
{
'adapter': 'lark',
'enable': False,
'app_id': 'cli_abcdefgh',
'app_secret': 'XXXXXXXXXX',
'bot_name': 'LangBot',
'enable-webhook': False,
'port': 2285,
'encrypt-key': 'xxxxxxxxx',
}
)
await self.ap.platform_cfg.dump_config()

View File

@@ -3,21 +3,21 @@ from __future__ import annotations
from .. import migration
@migration.migration_class("lmstudio-config", 22)
@migration.migration_class('lmstudio-config', 22)
class LmStudioConfigMigration(migration.Migration):
"""迁移"""
async def need_migrate(self) -> bool:
"""判断当前环境是否需要运行此迁移"""
return 'lmstudio-chat-completions' not in self.ap.provider_cfg.data['requester']
async def run(self):
"""执行迁移"""
self.ap.provider_cfg.data['requester']['lmstudio-chat-completions'] = {
"base-url": "http://127.0.0.1:1234/v1",
"args": {},
"timeout": 120
'base-url': 'http://127.0.0.1:1234/v1',
'args': {},
'timeout': 120,
}
await self.ap.provider_cfg.dump_config()

View File

@@ -3,25 +3,25 @@ from __future__ import annotations
from .. import migration
@migration.migration_class("siliconflow-config", 23)
@migration.migration_class('siliconflow-config', 23)
class SiliconFlowConfigMigration(migration.Migration):
"""迁移"""
async def need_migrate(self) -> bool:
"""判断当前环境是否需要运行此迁移"""
return 'siliconflow-chat-completions' not in self.ap.provider_cfg.data['requester']
return (
'siliconflow-chat-completions' not in self.ap.provider_cfg.data['requester']
)
async def run(self):
"""执行迁移"""
self.ap.provider_cfg.data['keys']['siliconflow'] = [
"xxxxxxx"
]
self.ap.provider_cfg.data['keys']['siliconflow'] = ['xxxxxxx']
self.ap.provider_cfg.data['requester']['siliconflow-chat-completions'] = {
"base-url": "https://api.siliconflow.cn/v1",
"args": {},
"timeout": 120
'base-url': 'https://api.siliconflow.cn/v1',
'args': {},
'timeout': 120,
}
await self.ap.provider_cfg.dump_config()

View File

@@ -3,13 +3,13 @@ from __future__ import annotations
from .. import migration
@migration.migration_class("discord-config", 24)
@migration.migration_class('discord-config', 24)
class DiscordConfigMigration(migration.Migration):
"""迁移"""
async def need_migrate(self) -> bool:
"""判断当前环境是否需要运行此迁移"""
# for adapter in self.ap.platform_cfg.data['platform-adapters']:
# if adapter['adapter'] == 'discord':
# return False
@@ -19,11 +19,13 @@ class DiscordConfigMigration(migration.Migration):
async def run(self):
"""执行迁移"""
self.ap.platform_cfg.data['platform-adapters'].append({
"adapter": "discord",
"enable": False,
"client_id": "1234567890",
"token": "XXXXXXXXXX"
})
self.ap.platform_cfg.data['platform-adapters'].append(
{
'adapter': 'discord',
'enable': False,
'client_id': '1234567890',
'token': 'XXXXXXXXXX',
}
)
await self.ap.platform_cfg.dump_config()

View File

@@ -3,13 +3,13 @@ from __future__ import annotations
from .. import migration
@migration.migration_class("gewechat-config", 25)
@migration.migration_class('gewechat-config', 25)
class GewechatConfigMigration(migration.Migration):
"""迁移"""
async def need_migrate(self) -> bool:
"""判断当前环境是否需要运行此迁移"""
# for adapter in self.ap.platform_cfg.data['platform-adapters']:
# if adapter['adapter'] == 'gewechat':
# return False
@@ -19,15 +19,17 @@ class GewechatConfigMigration(migration.Migration):
async def run(self):
"""执行迁移"""
self.ap.platform_cfg.data['platform-adapters'].append({
"adapter": "gewechat",
"enable": False,
"gewechat_url": "http://your-gewechat-server:2531",
"gewechat_file_url": "http://your-gewechat-server:2532",
"port": 2286,
"callback_url": "http://your-callback-url:2286/gewechat/callback",
"app_id": "",
"token": ""
})
self.ap.platform_cfg.data['platform-adapters'].append(
{
'adapter': 'gewechat',
'enable': False,
'gewechat_url': 'http://your-gewechat-server:2531',
'gewechat_file_url': 'http://your-gewechat-server:2532',
'port': 2286,
'callback_url': 'http://your-callback-url:2286/gewechat/callback',
'app_id': '',
'token': '',
}
)
await self.ap.platform_cfg.dump_config()

View File

@@ -3,13 +3,13 @@ from __future__ import annotations
from .. import migration
@migration.migration_class("qqofficial-config", 26)
@migration.migration_class('qqofficial-config', 26)
class QQOfficialConfigMigration(migration.Migration):
"""迁移"""
async def need_migrate(self) -> bool:
"""判断当前环境是否需要运行此迁移"""
# for adapter in self.ap.platform_cfg.data['platform-adapters']:
# if adapter['adapter'] == 'qqofficial':
# return False
@@ -19,13 +19,15 @@ class QQOfficialConfigMigration(migration.Migration):
async def run(self):
"""执行迁移"""
self.ap.platform_cfg.data['platform-adapters'].append({
"adapter": "qqofficial",
"enable": False,
"appid": "",
"secret": "",
"port": 2284,
"token": ""
})
self.ap.platform_cfg.data['platform-adapters'].append(
{
'adapter': 'qqofficial',
'enable': False,
'appid': '',
'secret': '',
'port': 2284,
'token': '',
}
)
await self.ap.platform_cfg.dump_config()

View File

@@ -3,13 +3,13 @@ from __future__ import annotations
from .. import migration
@migration.migration_class("wx-official-account-config", 27)
@migration.migration_class('wx-official-account-config', 27)
class WXOfficialAccountConfigMigration(migration.Migration):
"""迁移"""
async def need_migrate(self) -> bool:
"""判断当前环境是否需要运行此迁移"""
# for adapter in self.ap.platform_cfg.data['platform-adapters']:
# if adapter['adapter'] == 'officialaccount':
# return False
@@ -19,15 +19,17 @@ class WXOfficialAccountConfigMigration(migration.Migration):
async def run(self):
"""执行迁移"""
self.ap.platform_cfg.data['platform-adapters'].append({
"adapter": "officialaccount",
"enable": False,
"token": "",
"EncodingAESKey": "",
"AppID": "",
"AppSecret": "",
"host": "0.0.0.0",
"port": 2287
})
self.ap.platform_cfg.data['platform-adapters'].append(
{
'adapter': 'officialaccount',
'enable': False,
'token': '',
'EncodingAESKey': '',
'AppID': '',
'AppSecret': '',
'host': '0.0.0.0',
'port': 2287,
}
)
await self.ap.platform_cfg.dump_config()

View File

@@ -3,25 +3,23 @@ from __future__ import annotations
from .. import migration
@migration.migration_class("bailian-requester-config", 28)
@migration.migration_class('bailian-requester-config', 28)
class BailianRequesterConfigMigration(migration.Migration):
"""迁移"""
async def need_migrate(self) -> bool:
"""判断当前环境是否需要运行此迁移"""
return 'bailian-chat-completions' not in self.ap.provider_cfg.data['requester']
async def run(self):
"""执行迁移"""
self.ap.provider_cfg.data['keys']['bailian'] = [
"sk-xxxxxxx"
]
self.ap.provider_cfg.data['keys']['bailian'] = ['sk-xxxxxxx']
self.ap.provider_cfg.data['requester']['bailian-chat-completions'] = {
"base-url": "https://dashscope.aliyuncs.com/compatible-mode/v1",
"args": {},
"timeout": 120
'base-url': 'https://dashscope.aliyuncs.com/compatible-mode/v1',
'args': {},
'timeout': 120,
}
await self.ap.provider_cfg.dump_config()

View File

@@ -3,7 +3,7 @@ from __future__ import annotations
from .. import migration
@migration.migration_class("dashscope-app-api-config", 29)
@migration.migration_class('dashscope-app-api-config', 29)
class DashscopeAppAPICfgMigration(migration.Migration):
"""迁移"""
@@ -14,20 +14,14 @@ class DashscopeAppAPICfgMigration(migration.Migration):
async def run(self):
"""执行迁移"""
self.ap.provider_cfg.data['dashscope-app-api'] = {
"app-type": "agent",
"api-key": "sk-1234567890",
"agent": {
"app-id": "Your_app_id",
"references_quote": "参考资料来自:"
'app-type': 'agent',
'api-key': 'sk-1234567890',
'agent': {'app-id': 'Your_app_id', 'references_quote': '参考资料来自:'},
'workflow': {
'app-id': 'Your_app_id',
'references_quote': '参考资料来自:',
'biz_params': {'city': '北京', 'date': '2023-08-10'},
},
"workflow": {
"app-id": "Your_app_id",
"references_quote": "参考资料来自:",
"biz_params": {
"city": "北京",
"date": "2023-08-10"
}
}
}
await self.ap.provider_cfg.dump_config()

View File

@@ -3,13 +3,13 @@ from __future__ import annotations
from .. import migration
@migration.migration_class("lark-config-cmpl", 30)
@migration.migration_class('lark-config-cmpl', 30)
class LarkConfigCmplMigration(migration.Migration):
"""迁移"""
async def need_migrate(self) -> bool:
"""判断当前环境是否需要运行此迁移"""
for adapter in self.ap.platform_cfg.data['platform-adapters']:
if adapter['adapter'] == 'lark':
if 'enable-webhook' not in adapter:
@@ -26,6 +26,6 @@ class LarkConfigCmplMigration(migration.Migration):
if 'port' not in adapter:
adapter['port'] = 2285
if 'encrypt-key' not in adapter:
adapter['encrypt-key'] = "xxxxxxxxx"
adapter['encrypt-key'] = 'xxxxxxxxx'
await self.ap.platform_cfg.dump_config()

View File

@@ -3,13 +3,13 @@ from __future__ import annotations
from .. import migration
@migration.migration_class("dingtalk-config", 31)
@migration.migration_class('dingtalk-config', 31)
class DingTalkConfigMigration(migration.Migration):
"""迁移"""
async def need_migrate(self) -> bool:
"""判断当前环境是否需要运行此迁移"""
# for adapter in self.ap.platform_cfg.data['platform-adapters']:
# if adapter['adapter'] == 'dingtalk':
# return False
@@ -19,13 +19,15 @@ class DingTalkConfigMigration(migration.Migration):
async def run(self):
"""执行迁移"""
self.ap.platform_cfg.data['platform-adapters'].append({
"adapter": "dingtalk",
"enable": False,
"client_id": "",
"client_secret": "",
"robot_code": "",
"robot_name": ""
})
self.ap.platform_cfg.data['platform-adapters'].append(
{
'adapter': 'dingtalk',
'enable': False,
'client_id': '',
'client_secret': '',
'robot_code': '',
'robot_name': '',
}
)
await self.ap.platform_cfg.dump_config()

View File

@@ -3,25 +3,23 @@ from __future__ import annotations
from .. import migration
@migration.migration_class("volcark-requester-config", 32)
@migration.migration_class('volcark-requester-config', 32)
class VolcArkRequesterConfigMigration(migration.Migration):
"""迁移"""
async def need_migrate(self) -> bool:
"""判断当前环境是否需要运行此迁移"""
return 'volcark-chat-completions' not in self.ap.provider_cfg.data['requester']
async def run(self):
"""执行迁移"""
self.ap.provider_cfg.data['keys']['volcark'] = [
"xxxxxxxx"
]
self.ap.provider_cfg.data['keys']['volcark'] = ['xxxxxxxx']
self.ap.provider_cfg.data['requester']['volcark-chat-completions'] = {
"base-url": "https://ark.cn-beijing.volces.com/api/v3",
"args": {},
"timeout": 120
'base-url': 'https://ark.cn-beijing.volces.com/api/v3',
'args': {},
'timeout': 120,
}
await self.ap.provider_cfg.dump_config()

View File

@@ -3,24 +3,27 @@ from __future__ import annotations
from .. import migration
@migration.migration_class("dify-thinking-config", 33)
@migration.migration_class('dify-thinking-config', 33)
class DifyThinkingConfigMigration(migration.Migration):
"""迁移"""
async def need_migrate(self) -> bool:
"""判断当前环境是否需要运行此迁移"""
if 'options' not in self.ap.provider_cfg.data["dify-service-api"]:
if 'options' not in self.ap.provider_cfg.data['dify-service-api']:
return True
if 'convert-thinking-tips' not in self.ap.provider_cfg.data["dify-service-api"]["options"]:
if (
'convert-thinking-tips'
not in self.ap.provider_cfg.data['dify-service-api']['options']
):
return True
return False
async def run(self):
"""执行迁移"""
self.ap.provider_cfg.data["dify-service-api"]["options"] = {
"convert-thinking-tips": "plain"
self.ap.provider_cfg.data['dify-service-api']['options'] = {
'convert-thinking-tips': 'plain'
}
await self.ap.provider_cfg.dump_config()

View File

@@ -5,7 +5,7 @@ from urllib.parse import urlparse
from .. import migration
@migration.migration_class("gewechat-file-url-config", 34)
@migration.migration_class('gewechat-file-url-config', 34)
class GewechatFileUrlConfigMigration(migration.Migration):
"""迁移"""
@@ -24,6 +24,8 @@ class GewechatFileUrlConfigMigration(migration.Migration):
if adapter['adapter'] == 'gewechat':
if 'gewechat_file_url' not in adapter:
parsed_url = urlparse(adapter['gewechat_url'])
adapter['gewechat_file_url'] = f"{parsed_url.scheme}://{parsed_url.hostname}:2532"
adapter['gewechat_file_url'] = (
f'{parsed_url.scheme}://{parsed_url.hostname}:2532'
)
await self.ap.platform_cfg.dump_config()

View File

@@ -3,7 +3,7 @@ from __future__ import annotations
from .. import migration
@migration.migration_class("wxoa-mode", 35)
@migration.migration_class('wxoa-mode', 35)
class WxoaModeMigration(migration.Migration):
"""迁移"""

View File

@@ -3,7 +3,7 @@ from __future__ import annotations
from .. import migration
@migration.migration_class("wxoa-loading-message", 36)
@migration.migration_class('wxoa-loading-message', 36)
class WxoaLoadingMessageMigration(migration.Migration):
"""迁移"""

View File

@@ -3,7 +3,7 @@ from __future__ import annotations
from .. import migration
@migration.migration_class("mcp-config", 37)
@migration.migration_class('mcp-config', 37)
class MCPConfigMigration(migration.Migration):
"""迁移"""
@@ -13,8 +13,6 @@ class MCPConfigMigration(migration.Migration):
async def run(self):
"""执行迁移"""
self.ap.provider_cfg.data['mcp'] = {
"servers": []
}
self.ap.provider_cfg.data['mcp'] = {'servers': []}
await self.ap.provider_cfg.dump_config()

View File

@@ -7,9 +7,10 @@ from . import app
preregistered_notes: list[typing.Type[LaunchNote]] = []
def note_class(name: str, number: int):
"""注册一个启动信息
"""
"""注册一个启动信息"""
def decorator(cls: typing.Type[LaunchNote]) -> typing.Type[LaunchNote]:
cls.name = name
cls.number = number
@@ -20,8 +21,8 @@ def note_class(name: str, number: int):
class LaunchNote(abc.ABC):
"""启动信息
"""
"""启动信息"""
name: str
number: int
@@ -33,12 +34,10 @@ class LaunchNote(abc.ABC):
@abc.abstractmethod
async def need_show(self) -> bool:
"""判断当前环境是否需要显示此启动信息
"""
"""判断当前环境是否需要显示此启动信息"""
pass
@abc.abstractmethod
async def yield_note(self) -> typing.AsyncGenerator[typing.Tuple[str, int], None]:
"""生成启动信息
"""
"""生成启动信息"""
pass

View File

@@ -2,19 +2,17 @@ from __future__ import annotations
import typing
from .. import note, app
from .. import note
@note.note_class("ClassicNotes", 1)
@note.note_class('ClassicNotes', 1)
class ClassicNotes(note.LaunchNote):
"""经典启动信息
"""
"""经典启动信息"""
async def need_show(self) -> bool:
return True
async def yield_note(self) -> typing.AsyncGenerator[typing.Tuple[str, int], None]:
yield await self.ap.ann_mgr.show_announcements()
yield await self.ap.ver_mgr.show_version_update()
yield await self.ap.ver_mgr.show_version_update()

View File

@@ -2,20 +2,20 @@ from __future__ import annotations
import typing
import os
import sys
import logging
from .. import note, app
from .. import note
@note.note_class("SelectionModeOnWindows", 2)
@note.note_class('SelectionModeOnWindows', 2)
class SelectionModeOnWindows(note.LaunchNote):
"""Windows 上的选择模式提示信息
"""
"""Windows 上的选择模式提示信息"""
async def need_show(self) -> bool:
return os.name == 'nt'
async def yield_note(self) -> typing.AsyncGenerator[typing.Tuple[str, int], None]:
yield """您正在使用 Windows 系统,若窗口左上角显示处于”选择“模式,程序将被暂停运行,此时请右键窗口中空白区域退出选择模式。""", logging.INFO
yield (
"""您正在使用 Windows 系统,若窗口左上角显示处于”选择“模式,程序将被暂停运行,此时请右键窗口中空白区域退出选择模式。""",
logging.INFO,
)

View File

@@ -1,21 +1,17 @@
from __future__ import annotations
import typing
import os
import sys
import logging
from .. import note, app
from .. import note
@note.note_class("PrintVersion", 3)
@note.note_class('PrintVersion', 3)
class PrintVersion(note.LaunchNote):
"""Print Version Information
"""
"""Print Version Information"""
async def need_show(self) -> bool:
return True
async def yield_note(self) -> typing.AsyncGenerator[typing.Tuple[str, int], None]:
yield f"Current Version: {self.ap.ver_mgr.get_current_version()}", logging.INFO
yield f'Current Version: {self.ap.ver_mgr.get_current_version()}', logging.INFO

View File

@@ -12,9 +12,8 @@ preregistered_stages: dict[str, typing.Type[BootingStage]] = {}
当前阶段暂不支持扩展
"""
def stage_class(
name: str
):
def stage_class(name: str):
def decorator(cls: typing.Type[BootingStage]) -> typing.Type[BootingStage]:
preregistered_stages[name] = cls
return cls
@@ -23,12 +22,11 @@ def stage_class(
class BootingStage(abc.ABC):
"""启动阶段
"""
"""启动阶段"""
name: str = None
@abc.abstractmethod
async def run(self, ap: app.Application):
"""启动
"""
"""启动"""
pass

View File

@@ -1,6 +1,5 @@
from __future__ import annotations
import sys
from .. import stage, app
from ...utils import version, proxy, announce, platform
@@ -24,26 +23,22 @@ from ...utils import logcache
from .. import taskmgr
@stage.stage_class("BuildAppStage")
@stage.stage_class('BuildAppStage')
class BuildAppStage(stage.BootingStage):
"""构建应用阶段
"""
"""构建应用阶段"""
async def run(self, ap: app.Application):
"""构建app对象的各个组件对象并初始化
"""
"""构建app对象的各个组件对象并初始化"""
ap.task_mgr = taskmgr.AsyncTaskManager(ap)
discover = discover_engine.ComponentDiscoveryEngine(ap)
discover.discover_blueprint(
"components.yaml"
)
discover.discover_blueprint('components.yaml')
ap.discover = discover
proxy_mgr = proxy.ProxyManager(ap)
await proxy_mgr.initialize()
ap.proxy_mgr = proxy_mgr
ver_mgr = version.VersionManager(ap)
await ver_mgr.initialize()
ap.ver_mgr = ver_mgr
@@ -52,14 +47,14 @@ class BuildAppStage(stage.BootingStage):
ap,
backend_url=ap.instance_config.data['telemetry']['url'],
basic_info={
"host_id": identifier.identifier["host_id"],
"instance_id": identifier.identifier["instance_id"],
"semantic_version": ver_mgr.get_current_version(),
"platform": platform.get_platform(),
'host_id': identifier.identifier['host_id'],
'instance_id': identifier.identifier['instance_id'],
'semantic_version': ver_mgr.get_current_version(),
'platform': platform.get_platform(),
},
runtime_info={
"admin_id": "{}".format(ap.instance_config.data["admins"]),
"msg_source": str([]),
'admin_id': '{}'.format(ap.instance_config.data['admins']),
'msg_source': str([]),
},
)
ap.ctr_mgr = center_v2_api

View File

@@ -1,20 +1,17 @@
from __future__ import annotations
import secrets
import os
from .. import stage, app
@stage.stage_class("GenKeysStage")
@stage.stage_class('GenKeysStage')
class GenKeysStage(stage.BootingStage):
"""生成密钥阶段
"""
"""生成密钥阶段"""
async def run(self, ap: app.Application):
"""启动
"""
"""启动"""
if not ap.instance_config.data['system']['jwt']['secret']:
ap.instance_config.data['system']['jwt']['secret'] = secrets.token_hex(16)
await ap.instance_config.dump_config()

View File

@@ -7,45 +7,80 @@ from .. import stage, app
from ..bootutils import config
@stage.stage_class("LoadConfigStage")
@stage.stage_class('LoadConfigStage')
class LoadConfigStage(stage.BootingStage):
"""加载配置文件阶段
"""
"""加载配置文件阶段"""
async def run(self, ap: app.Application):
"""启动
"""
"""启动"""
# ======= deprecated =======
if os.path.exists("data/config/command.json"):
ap.command_cfg = await config.load_json_config("data/config/command.json", "templates/legacy/command.json", completion=False)
if os.path.exists('data/config/command.json'):
ap.command_cfg = await config.load_json_config(
'data/config/command.json',
'templates/legacy/command.json',
completion=False,
)
if os.path.exists("data/config/pipeline.json"):
ap.pipeline_cfg = await config.load_json_config("data/config/pipeline.json", "templates/legacy/pipeline.json", completion=False)
if os.path.exists('data/config/pipeline.json'):
ap.pipeline_cfg = await config.load_json_config(
'data/config/pipeline.json',
'templates/legacy/pipeline.json',
completion=False,
)
if os.path.exists("data/config/platform.json"):
ap.platform_cfg = await config.load_json_config("data/config/platform.json", "templates/legacy/platform.json", completion=False)
if os.path.exists('data/config/platform.json'):
ap.platform_cfg = await config.load_json_config(
'data/config/platform.json',
'templates/legacy/platform.json',
completion=False,
)
if os.path.exists("data/config/provider.json"):
ap.provider_cfg = await config.load_json_config("data/config/provider.json", "templates/legacy/provider.json", completion=False)
if os.path.exists('data/config/provider.json'):
ap.provider_cfg = await config.load_json_config(
'data/config/provider.json',
'templates/legacy/provider.json',
completion=False,
)
if os.path.exists("data/config/system.json"):
ap.system_cfg = await config.load_json_config("data/config/system.json", "templates/legacy/system.json", completion=False)
if os.path.exists('data/config/system.json'):
ap.system_cfg = await config.load_json_config(
'data/config/system.json',
'templates/legacy/system.json',
completion=False,
)
if os.path.exists("data/metadata/instance-secret.json"):
ap.instance_secret_meta = await config.load_json_config("data/metadata/instance-secret.json", template_data={
'jwt_secret': secrets.token_hex(16)
})
if os.path.exists('data/metadata/instance-secret.json'):
ap.instance_secret_meta = await config.load_json_config(
'data/metadata/instance-secret.json',
template_data={'jwt_secret': secrets.token_hex(16)},
)
await ap.instance_secret_meta.dump_config()
# ======= deprecated =======
ap.instance_config = await config.load_yaml_config("data/config.yaml", "templates/config.yaml", completion=False)
ap.instance_config = await config.load_yaml_config(
'data/config.yaml', 'templates/config.yaml', completion=False
)
await ap.instance_config.dump_config()
ap.sensitive_meta = await config.load_json_config("data/metadata/sensitive-words.json", "templates/metadata/sensitive-words.json")
ap.sensitive_meta = await config.load_json_config(
'data/metadata/sensitive-words.json',
'templates/metadata/sensitive-words.json',
)
await ap.sensitive_meta.dump_config()
ap.pipeline_config_meta_trigger = await config.load_yaml_config("templates/metadata/pipeline/trigger.yaml", "templates/metadata/pipeline/trigger.yaml")
ap.pipeline_config_meta_safety = await config.load_yaml_config("templates/metadata/pipeline/safety.yaml", "templates/metadata/pipeline/safety.yaml")
ap.pipeline_config_meta_ai = await config.load_yaml_config("templates/metadata/pipeline/ai.yaml", "templates/metadata/pipeline/ai.yaml")
ap.pipeline_config_meta_output = await config.load_yaml_config("templates/metadata/pipeline/output.yaml", "templates/metadata/pipeline/output.yaml")
ap.pipeline_config_meta_trigger = await config.load_yaml_config(
'templates/metadata/pipeline/trigger.yaml',
'templates/metadata/pipeline/trigger.yaml',
)
ap.pipeline_config_meta_safety = await config.load_yaml_config(
'templates/metadata/pipeline/safety.yaml',
'templates/metadata/pipeline/safety.yaml',
)
ap.pipeline_config_meta_ai = await config.load_yaml_config(
'templates/metadata/pipeline/ai.yaml', 'templates/metadata/pipeline/ai.yaml'
)
ap.pipeline_config_meta_output = await config.load_yaml_config(
'templates/metadata/pipeline/output.yaml',
'templates/metadata/pipeline/output.yaml',
)

View File

@@ -1,37 +1,30 @@
from __future__ import annotations
import importlib
import os
from .. import stage, app
from .. import migration
from ..migrations import m001_sensitive_word_migration, m002_openai_config_migration, m003_anthropic_requester_cfg_completion, m004_moonshot_cfg_completion
from ..migrations import m005_deepseek_cfg_completion, m006_vision_config, m007_qcg_center_url, m008_ad_fixwin_config_migrate, m009_msg_truncator_cfg
from ..migrations import m010_ollama_requester_config, m011_command_prefix_config, m012_runner_config, m013_http_api_config, m014_force_delay_config
from ..migrations import m015_gitee_ai_config, m016_dify_service_api, m017_dify_api_timeout_params, m018_xai_config, m019_zhipuai_config
from ..migrations import m020_wecom_config, m021_lark_config, m022_lmstudio_config, m023_siliconflow_config, m024_discord_config, m025_gewechat_config
from ..migrations import m026_qqofficial_config, m027_wx_official_account_config, m028_aliyun_requester_config
from ..migrations import m029_dashscope_app_api_config, m030_lark_config_cmpl, m031_dingtalk_config, m032_volcark_config
from ..migrations import m033_dify_thinking_config, m034_gewechat_file_url_config, m035_wxoa_mode, m036_wxoa_loading_message
from ..migrations import m037_mcp_config
from ...utils import importutil
from .. import migrations
importutil.import_modules_in_pkg(migrations)
@stage.stage_class("MigrationStage")
@stage.stage_class('MigrationStage')
class MigrationStage(stage.BootingStage):
"""迁移阶段
"""
"""迁移阶段"""
async def run(self, ap: app.Application):
"""启动
"""
"""启动"""
if any([
ap.command_cfg is None,
ap.pipeline_cfg is None,
ap.platform_cfg is None,
ap.provider_cfg is None,
ap.system_cfg is None,
]): # only run migration when version is 3.x
if any(
[
ap.command_cfg is None,
ap.pipeline_cfg is None,
ap.platform_cfg is None,
ap.provider_cfg is None,
ap.system_cfg is None,
]
): # only run migration when version is 3.x
return
migrations = migration.preregistered_migrations

View File

@@ -1,8 +1,6 @@
from __future__ import annotations
import logging
import asyncio
from datetime import datetime
from .. import stage, app
from ..bootutils import log
@@ -12,6 +10,7 @@ class PersistenceHandler(logging.Handler, object):
"""
保存日志到数据库
"""
ap: app.Application
def __init__(self, name, ap: app.Application):
@@ -28,19 +27,17 @@ class PersistenceHandler(logging.Handler, object):
msg = self.format(record)
if self.ap.log_cache is not None:
self.ap.log_cache.add_log(msg)
except Exception:
self.handleError(record)
@stage.stage_class("SetupLoggerStage")
@stage.stage_class('SetupLoggerStage')
class SetupLoggerStage(stage.BootingStage):
"""设置日志器阶段
"""
"""设置日志器阶段"""
async def run(self, ap: app.Application):
"""启动
"""
"""启动"""
persistence_handler = PersistenceHandler('LoggerHandler', ap)
extra_handlers = []

View File

@@ -1,16 +1,18 @@
from __future__ import annotations
from .. import stage, app, note
from ..notes import n001_classic_msgs, n002_selection_mode_on_windows, n003_print_version
from ...utils import importutil
from .. import notes
importutil.import_modules_in_pkg(notes)
@stage.stage_class("ShowNotesStage")
@stage.stage_class('ShowNotesStage')
class ShowNotesStage(stage.BootingStage):
"""显示启动信息阶段
"""
"""显示启动信息阶段"""
async def run(self, ap: app.Application):
# 排序
note.preregistered_notes.sort(key=lambda x: x.number)
@@ -24,5 +26,5 @@ class ShowNotesStage(stage.BootingStage):
msg, level = ret
if msg:
ap.logger.log(level, msg)
except Exception as e:
except Exception:
continue

View File

@@ -3,7 +3,6 @@ from __future__ import annotations
import asyncio
import typing
import datetime
import traceback
from . import app
from . import entities as core_entities
@@ -19,11 +18,11 @@ class TaskContext:
"""记录日志"""
def __init__(self):
self.current_action = "default"
self.log = ""
self.current_action = 'default'
self.log = ''
def _log(self, msg: str):
self.log += msg + "\n"
self.log += msg + '\n'
def set_current_action(self, action: str):
self.current_action = action
@@ -37,16 +36,16 @@ class TaskContext:
self.set_current_action(action)
self._log(
f"{datetime.datetime.now().strftime('%Y-%m-%d %H:%M:%S')} | {self.current_action} | {msg}"
f'{datetime.datetime.now().strftime("%Y-%m-%d %H:%M:%S")} | {self.current_action} | {msg}'
)
def to_dict(self) -> dict:
return {"current_action": self.current_action, "log": self.log}
return {'current_action': self.current_action, 'log': self.log}
@staticmethod
def new() -> TaskContext:
return TaskContext()
@staticmethod
def placeholder() -> TaskContext:
global placeholder_context
@@ -69,16 +68,16 @@ class TaskWrapper:
id: int
"""任务ID"""
task_type: str = "system" # 任务类型: system 或 user
task_type: str = 'system' # 任务类型: system 或 user
"""任务类型"""
kind: str = "system_task" # 由发起者确定任务种类,通常同质化的任务种类相同
kind: str = 'system_task' # 由发起者确定任务种类,通常同质化的任务种类相同
"""任务种类"""
name: str = ""
name: str = ''
"""任务唯一名称"""
label: str = ""
label: str = ''
"""任务显示名称"""
task_context: TaskContext
@@ -100,12 +99,14 @@ class TaskWrapper:
self,
ap: app.Application,
coro: typing.Coroutine,
task_type: str = "system",
kind: str = "system_task",
name: str = "",
label: str = "",
task_type: str = 'system',
kind: str = 'system_task',
name: str = '',
label: str = '',
context: TaskContext = None,
scopes: list[core_entities.LifecycleControlScope] = [core_entities.LifecycleControlScope.APPLICATION],
scopes: list[core_entities.LifecycleControlScope] = [
core_entities.LifecycleControlScope.APPLICATION
],
):
self.id = TaskWrapper._id_index
TaskWrapper._id_index += 1
@@ -115,7 +116,7 @@ class TaskWrapper:
self.task_type = task_type
self.kind = kind
self.name = name
self.label = label if label != "" else name
self.label = label if label != '' else name
self.task.set_name(name)
self.scopes = scopes
@@ -125,43 +126,46 @@ class TaskWrapper:
if self.task_stack is None:
self.task_stack = self.task.get_stack()
return exception
except:
except Exception:
return None
def assume_result(self):
try:
return self.task.result()
except:
except Exception:
return None
def to_dict(self) -> dict:
exception_traceback = None
if self.assume_exception() is not None:
exception_traceback = 'Traceback (most recent call last):\n'
for frame in self.task_stack:
exception_traceback += f" File \"{frame.f_code.co_filename}\", line {frame.f_lineno}, in {frame.f_code.co_name}\n"
exception_traceback += f' File "{frame.f_code.co_filename}", line {frame.f_lineno}, in {frame.f_code.co_name}\n'
exception_traceback += f" {self.assume_exception().__str__()}\n"
exception_traceback += f' {self.assume_exception().__str__()}\n'
return {
"id": self.id,
"task_type": self.task_type,
"kind": self.kind,
"name": self.name,
"label": self.label,
"scopes": [scope.value for scope in self.scopes],
"task_context": self.task_context.to_dict(),
"runtime": {
"done": self.task.done(),
"state": self.task._state,
"exception": self.assume_exception().__str__() if self.assume_exception() is not None else None,
"exception_traceback": exception_traceback,
"result": self.assume_result().__str__() if self.assume_result() is not None else None,
'id': self.id,
'task_type': self.task_type,
'kind': self.kind,
'name': self.name,
'label': self.label,
'scopes': [scope.value for scope in self.scopes],
'task_context': self.task_context.to_dict(),
'runtime': {
'done': self.task.done(),
'state': self.task._state,
'exception': self.assume_exception().__str__()
if self.assume_exception() is not None
else None,
'exception_traceback': exception_traceback,
'result': self.assume_result().__str__()
if self.assume_result() is not None
else None,
},
}
def cancel(self):
self.task.cancel()
@@ -182,27 +186,33 @@ class AsyncTaskManager:
def create_task(
self,
coro: typing.Coroutine,
task_type: str = "system",
kind: str = "system-task",
name: str = "",
label: str = "",
task_type: str = 'system',
kind: str = 'system-task',
name: str = '',
label: str = '',
context: TaskContext = None,
scopes: list[core_entities.LifecycleControlScope] = [core_entities.LifecycleControlScope.APPLICATION],
scopes: list[core_entities.LifecycleControlScope] = [
core_entities.LifecycleControlScope.APPLICATION
],
) -> TaskWrapper:
wrapper = TaskWrapper(self.ap, coro, task_type, kind, name, label, context, scopes)
wrapper = TaskWrapper(
self.ap, coro, task_type, kind, name, label, context, scopes
)
self.tasks.append(wrapper)
return wrapper
def create_user_task(
self,
coro: typing.Coroutine,
kind: str = "user-task",
name: str = "",
label: str = "",
kind: str = 'user-task',
name: str = '',
label: str = '',
context: TaskContext = None,
scopes: list[core_entities.LifecycleControlScope] = [core_entities.LifecycleControlScope.APPLICATION],
scopes: list[core_entities.LifecycleControlScope] = [
core_entities.LifecycleControlScope.APPLICATION
],
) -> TaskWrapper:
return self.create_task(coro, "user", kind, name, label, context, scopes)
return self.create_task(coro, 'user', kind, name, label, context, scopes)
async def wait_all(self):
await asyncio.gather(*[t.task for t in self.tasks], return_exceptions=True)
@@ -215,12 +225,12 @@ class AsyncTaskManager:
type: str = None,
) -> dict:
return {
"tasks": [
'tasks': [
t.to_dict() for t in self.tasks if type is None or t.task_type == type
],
"id_index": TaskWrapper._id_index,
'id_index': TaskWrapper._id_index,
}
def get_task_by_id(self, id: int) -> TaskWrapper | None:
for t in self.tasks:
if t.id == id:
@@ -229,9 +239,7 @@ class AsyncTaskManager:
def cancel_by_scope(self, scope: core_entities.LifecycleControlScope):
for wrapper in self.tasks:
if not wrapper.task.done() and scope in wrapper.scopes:
wrapper.task.cancel()
def cancel_task(self, task_id: int):