From a167cbfbe19fada2ca356dd8e3d59ac28226efce Mon Sep 17 00:00:00 2001 From: XcantloadX <3188996979@qq.com> Date: Sat, 26 Jul 2025 13:26:01 +0800 Subject: [PATCH] =?UTF-8?q?feat(core):=20=E6=94=AF=E6=8C=81=E4=BB=BB?= =?UTF-8?q?=E5=8A=A1=E6=89=A7=E8=A1=8C=E4=B8=AD=E5=8F=AA=E8=B7=B3=E8=BF=87?= =?UTF-8?q?=E6=88=96=E5=81=9C=E6=AD=A2=E5=BD=93=E5=89=8D=E4=BB=BB=E5=8A=A1?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- kotonebot/backend/bot.py | 15 ++++++++++----- kotonebot/errors.py | 7 +++++-- 2 files changed, 15 insertions(+), 7 deletions(-) diff --git a/kotonebot/backend/bot.py b/kotonebot/backend/bot.py index f5c9e09..fd146a1 100644 --- a/kotonebot/backend/bot.py +++ b/kotonebot/backend/bot.py @@ -12,6 +12,7 @@ from kotonebot.client import Device from kotonebot.client.host.protocol import Instance from kotonebot.backend.context import init_context, vars from kotonebot.backend.context import task_registry, action_registry, Task, Action +from kotonebot.errors import StopCurrentTask log_stream = io.StringIO() stream_handler = logging.StreamHandler(log_stream) @@ -19,10 +20,11 @@ stream_handler.setFormatter(logging.Formatter('[%(asctime)s] [%(levelname)s] [%( logging.getLogger('kotonebot').addHandler(stream_handler) logger = logging.getLogger(__name__) +TaskStatusValue = Literal['pending', 'running', 'finished', 'error', 'cancelled', 'stopped'] @dataclass class TaskStatus: task: Task - status: Literal['pending', 'running', 'finished', 'error', 'cancelled'] + status: TaskStatusValue @dataclass class RunStatus: @@ -73,7 +75,7 @@ class Event(Generic[Params, Return]): class KotoneBotEvents: def __init__(self): self.task_status_changed = Event[ - [Task, Literal['pending', 'running', 'finished', 'error', 'cancelled']], None + [Task, TaskStatusValue], None ]() self.task_error = Event[ [Task, Exception], None @@ -186,6 +188,9 @@ class KotoneBot: try: task.func() self.events.task_status_changed.trigger(task, 'finished') + except StopCurrentTask: + logger.info(f'Task skipped/stopped: {task.name}') + self.events.task_status_changed.trigger(task, 'stopped') # 用户中止 except KeyboardInterrupt as e: logger.exception('Keyboard interrupt detected.') @@ -205,8 +210,8 @@ class KotoneBot: for task1 in tasks[tasks.index(task)+1:]: self.events.task_status_changed.trigger(task1, 'cancelled') break - logger.info(f'Task finished: {task.name}') - logger.info('All tasks finished.') + logger.info(f'Task ended: {task.name}') + logger.info('All tasks ended.') self.events.finished.trigger() def run_all(self) -> None: @@ -228,7 +233,7 @@ class KotoneBot: self.events.finished -= _on_finished self.events.task_status_changed -= _on_task_status_changed - def _on_task_status_changed(task: Task, status: Literal['pending', 'running', 'finished', 'error', 'cancelled']): + def _on_task_status_changed(task: Task, status: TaskStatusValue): def _find(task: Task) -> TaskStatus: for task_status in run_status.tasks: if task_status.task == task: diff --git a/kotonebot/errors.py b/kotonebot/errors.py index d13e62c..924b52a 100644 --- a/kotonebot/errors.py +++ b/kotonebot/errors.py @@ -31,7 +31,10 @@ class UnscalableResolutionError(KotonebotError): self.screen_size = screen_size super().__init__(f'Cannot scale to target resolution {target_resolution}. ' f'Screen size: {screen_size}') - + class ContextNotInitializedError(KotonebotError): def __init__(self, msg: str = 'Context not initialized'): - super().__init__(msg) \ No newline at end of file + super().__init__(msg) + +class StopCurrentTask(KotonebotError): + pass \ No newline at end of file