This commit is contained in:
tt-P607
2025-11-01 21:39:51 +08:00
20 changed files with 107 additions and 49 deletions

View File

@@ -14,6 +14,9 @@ from src.config.config import global_config
logger = get_logger("plan_executor")
# 全局背景任务集合
_background_tasks = set()
class ChatterPlanExecutor:
"""
@@ -89,7 +92,9 @@ class ChatterPlanExecutor:
# 将其他动作放入后台任务执行,避免阻塞主流程
if other_actions:
asyncio.create_task(self._execute_other_actions(other_actions, plan))
task = asyncio.create_task(self._execute_other_actions(other_actions, plan))
_background_tasks.add(task)
task.add_done_callback(_background_tasks.discard)
logger.info(f"已将 {len(other_actions)} 个其他动作放入后台任务执行。")
# 注意:后台任务的结果不会立即计入本次返回的统计数据

View File

@@ -11,6 +11,9 @@ from src.plugin_system import BasePlugin, ComponentInfo, register_plugin
from src.plugin_system.base.component_types import PermissionNodeField
from src.plugin_system.base.config_types import ConfigField
# 全局背景任务集合
_background_tasks = set()
from .actions.read_feed_action import ReadFeedAction
from .actions.send_feed_action import SendFeedAction
from .commands.send_feed_command import SendFeedCommand
@@ -117,8 +120,14 @@ class MaiZoneRefactoredPlugin(BasePlugin):
logger.info("MaiZone重构版插件服务已注册。")
# --- 启动后台任务 ---
asyncio.create_task(scheduler_service.start())
asyncio.create_task(monitor_service.start())
task1 = asyncio.create_task(scheduler_service.start())
_background_tasks.add(task1)
task1.add_done_callback(_background_tasks.discard)
task2 = asyncio.create_task(monitor_service.start())
_background_tasks.add(task2)
task2.add_done_callback(_background_tasks.discard)
logger.info("MaiZone后台监控和定时任务已启动。")
def get_plugin_components(self) -> list[tuple[ComponentInfo, type]]:

View File

@@ -7,6 +7,7 @@ import base64
from collections.abc import Callable
from pathlib import Path
import aiofiles
import aiohttp
from src.common.logger import get_logger
@@ -86,8 +87,8 @@ class ImageService:
if b64_json:
image_bytes = base64.b64decode(b64_json)
file_path = Path(image_dir) / f"image_{i + 1}.png"
with open(file_path, "wb") as f:
f.write(image_bytes)
async with aiofiles.open(file_path, "wb") as f:
await f.write(image_bytes)
logger.info(f"成功保存AI图片到: {file_path}")
return True
else:

View File

@@ -12,6 +12,7 @@ from collections.abc import Callable
from pathlib import Path
from typing import Any
import aiofiles
import aiohttp
import bs4
import json5
@@ -397,8 +398,8 @@ class QZoneService:
}
# 成功获取后,异步写入本地文件作为备份
try:
with open(cookie_file_path, "wb") as f:
f.write(orjson.dumps(parsed_cookies))
async with aiofiles.open(cookie_file_path, "wb") as f:
await f.write(orjson.dumps(parsed_cookies))
logger.info(f"通过Napcat服务成功更新Cookie并已保存至: {cookie_file_path}")
except Exception as e:
logger.warning(f"保存Cookie到文件时出错: {e}")
@@ -413,8 +414,9 @@ class QZoneService:
logger.info("尝试从本地Cookie文件加载...")
if cookie_file_path.exists():
try:
with open(cookie_file_path, "rb") as f:
cookies = orjson.loads(f.read())
async with aiofiles.open(cookie_file_path, "rb") as f:
content = await f.read()
cookies = orjson.loads(content)
logger.info(f"成功从本地文件加载Cookie: {cookie_file_path}")
return cookies
except Exception as e:

View File

@@ -13,6 +13,8 @@ logger = get_logger("stt_whisper_plugin")
# 全局变量来缓存模型,避免重复加载
_whisper_model = None
_is_loading = False
_model_ready_event = asyncio.Event()
_background_tasks = set() # 背景任务集合
class LocalASRTool(BaseTool):
"""
@@ -29,7 +31,7 @@ class LocalASRTool(BaseTool):
"""
一个类方法,用于在插件加载时触发一次模型加载。
"""
global _whisper_model, _is_loading
global _whisper_model, _is_loading, _model_ready_event
if _whisper_model is None and not _is_loading:
_is_loading = True
try:
@@ -47,6 +49,7 @@ class LocalASRTool(BaseTool):
_whisper_model = None
finally:
_is_loading = False
_model_ready_event.set() # 通知等待的任务
async def execute(self, function_args: dict) -> str:
audio_path = function_args.get("audio_path")
@@ -55,9 +58,9 @@ class LocalASRTool(BaseTool):
return "错误:缺少 audio_path 参数。"
global _whisper_model
# 增强的等待逻辑:只要模型还没准备好,就一直等待后台加载任务完成
while _is_loading:
await asyncio.sleep(0.2)
# 使用 Event 等待模型加载完成
if _is_loading:
await _model_ready_event.wait()
if _whisper_model is None:
return "Whisper 模型加载失败,无法识别语音。"
@@ -90,7 +93,9 @@ class STTWhisperPlugin(BasePlugin):
from src.config.config import global_config
if global_config.voice.asr_provider == "local":
# 使用 create_task 在后台开始加载,不阻塞主流程
asyncio.create_task(LocalASRTool.load_model_once(self.config or {}))
task = asyncio.create_task(LocalASRTool.load_model_once(self.config or {}))
_background_tasks.add(task)
task.add_done_callback(_background_tasks.discard)
except Exception as e:
logger.error(f"触发 Whisper 模型预加载时出错: {e}")