kotonebot 0.4.0__py3-none-any.whl → 0.5.0__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (64) hide show
  1. kotonebot/__init__.py +39 -39
  2. kotonebot/backend/bot.py +312 -312
  3. kotonebot/backend/color.py +525 -525
  4. kotonebot/backend/context/__init__.py +3 -3
  5. kotonebot/backend/context/task_action.py +183 -183
  6. kotonebot/backend/core.py +129 -129
  7. kotonebot/backend/debug/entry.py +89 -89
  8. kotonebot/backend/debug/mock.py +78 -78
  9. kotonebot/backend/debug/server.py +222 -222
  10. kotonebot/backend/debug/vars.py +351 -351
  11. kotonebot/backend/dispatch.py +227 -227
  12. kotonebot/backend/flow_controller.py +196 -196
  13. kotonebot/backend/ocr.py +535 -529
  14. kotonebot/backend/preprocessor.py +103 -103
  15. kotonebot/client/__init__.py +9 -9
  16. kotonebot/client/device.py +528 -503
  17. kotonebot/client/fast_screenshot.py +377 -377
  18. kotonebot/client/host/__init__.py +43 -12
  19. kotonebot/client/host/adb_common.py +107 -103
  20. kotonebot/client/host/custom.py +118 -114
  21. kotonebot/client/host/leidian_host.py +196 -201
  22. kotonebot/client/host/mumu12_host.py +353 -358
  23. kotonebot/client/host/protocol.py +214 -213
  24. kotonebot/client/host/windows_common.py +58 -58
  25. kotonebot/client/implements/__init__.py +71 -15
  26. kotonebot/client/implements/adb.py +89 -85
  27. kotonebot/client/implements/adb_raw.py +162 -158
  28. kotonebot/client/implements/nemu_ipc/__init__.py +11 -7
  29. kotonebot/client/implements/nemu_ipc/external_renderer_ipc.py +284 -284
  30. kotonebot/client/implements/nemu_ipc/nemu_ipc.py +327 -327
  31. kotonebot/client/implements/remote_windows.py +188 -188
  32. kotonebot/client/implements/uiautomator2.py +85 -81
  33. kotonebot/client/implements/windows.py +176 -172
  34. kotonebot/client/protocol.py +69 -69
  35. kotonebot/client/registration.py +24 -24
  36. kotonebot/config/base_config.py +96 -96
  37. kotonebot/config/manager.py +36 -36
  38. kotonebot/errors.py +76 -71
  39. kotonebot/interop/win/__init__.py +10 -3
  40. kotonebot/interop/win/_mouse.py +311 -0
  41. kotonebot/interop/win/message_box.py +313 -313
  42. kotonebot/interop/win/reg.py +37 -37
  43. kotonebot/interop/win/shortcut.py +43 -43
  44. kotonebot/interop/win/task_dialog.py +513 -513
  45. kotonebot/logging/__init__.py +2 -2
  46. kotonebot/logging/log.py +17 -17
  47. kotonebot/primitives/__init__.py +17 -17
  48. kotonebot/primitives/geometry.py +862 -290
  49. kotonebot/primitives/visual.py +63 -63
  50. kotonebot/tools/mirror.py +354 -354
  51. kotonebot/ui/file_host/sensio.py +36 -36
  52. kotonebot/ui/file_host/tmp_send.py +54 -54
  53. kotonebot/ui/pushkit/__init__.py +3 -3
  54. kotonebot/ui/pushkit/image_host.py +88 -87
  55. kotonebot/ui/pushkit/protocol.py +13 -13
  56. kotonebot/ui/pushkit/wxpusher.py +54 -53
  57. kotonebot/ui/user.py +148 -148
  58. kotonebot/util.py +436 -436
  59. {kotonebot-0.4.0.dist-info → kotonebot-0.5.0.dist-info}/METADATA +82 -81
  60. kotonebot-0.5.0.dist-info/RECORD +71 -0
  61. {kotonebot-0.4.0.dist-info → kotonebot-0.5.0.dist-info}/licenses/LICENSE +673 -673
  62. kotonebot-0.4.0.dist-info/RECORD +0 -70
  63. {kotonebot-0.4.0.dist-info → kotonebot-0.5.0.dist-info}/WHEEL +0 -0
  64. {kotonebot-0.4.0.dist-info → kotonebot-0.5.0.dist-info}/top_level.txt +0 -0
@@ -1,197 +1,197 @@
1
- import time
2
- import logging
3
- import threading
4
- from typing import Literal
5
-
6
- logger = logging.getLogger(__name__)
7
-
8
- class FlowController:
9
- """
10
- 一个用于控制任务执行流程(如停止、暂停、恢复)的类。
11
-
12
- 这个类是线程安全的,提供了以下功能:
13
-
14
- * 停止任务执行(通过中断信号)
15
- * 暂停/恢复任务执行
16
- * 可中断和可暂停的 sleep 功能
17
- * 流程状态检查
18
-
19
- 使用方法::
20
-
21
- controller = FlowController()
22
-
23
- # 在任务的关键路径上调用检查
24
- controller.check()
25
-
26
- # 使用可控制的 sleep
27
- controller.sleep(1.0)
28
-
29
- # 外部控制
30
- controller.request_pause() # 暂停
31
- controller.request_resume() # 恢复
32
- controller.request_stop() # 停止
33
- """
34
-
35
- def __init__(self):
36
- self.interrupt_event: threading.Event = threading.Event()
37
- """中断事件,用于停止任务"""
38
-
39
- self.paused: bool = False
40
- """暂停标志"""
41
-
42
- self.pause_condition: threading.Condition = threading.Condition()
43
- """暂停条件变量,用于线程间同步"""
44
-
45
- def check(self) -> None:
46
- """
47
- 检查当前流程状态。
48
-
49
- 如果收到停止请求,则抛出 KeyboardInterrupt 异常。
50
- 如果收到暂停请求,则阻塞直到恢复。
51
-
52
- 这是核心的检查点方法,应在任务的关键路径上(如循环或等待前)调用。
53
-
54
- :raises KeyboardInterrupt: 当收到停止请求时
55
- """
56
- # 优先检查中断信号
57
- if self.interrupt_event.is_set():
58
- raise KeyboardInterrupt("User requested interrupt.")
59
-
60
- # 检查暂停状态
61
- with self.pause_condition:
62
- while self.paused:
63
- self.pause_condition.wait()
64
-
65
- def sleep(self, seconds: float) -> None:
66
- """
67
- 一个可被中断和暂停的 sleep 方法。
68
-
69
- 与标准的 time.sleep() 不同,这个方法会响应停止和暂停请求。
70
- 在暂停状态下,计时器会暂停,恢复后继续计时。
71
-
72
- :param seconds: 睡眠时间(秒)
73
- :raises KeyboardInterrupt: 当收到停止请求时
74
- """
75
- with self.pause_condition:
76
- end_time = time.time() + seconds
77
- while True:
78
- self.check() # 每次循环都检查状态
79
- remaining = end_time - time.time()
80
- if remaining <= 0:
81
- break
82
- # 等待指定时间或直到被唤醒
83
- self.pause_condition.wait(timeout=remaining)
84
-
85
- # 结束后再次检查状态
86
- self.check()
87
-
88
- def request_interrupt(self) -> None:
89
- """
90
- 请求停止任务。
91
-
92
- 设置中断信号,所有正在执行的任务将在下一个检查点停止。
93
- 停止的优先级高于暂停。
94
- """
95
- logger.info('Interrupt requested.')
96
- self.interrupt_event.set()
97
-
98
- def request_pause(self, *, wait_resume: bool = False) -> None:
99
- """
100
- 请求暂停任务。
101
-
102
- 设置暂停标志,所有正在执行的任务将在下一个检查点暂停。
103
- 如果任务已经暂停,此操作无效果。
104
- """
105
- with self.pause_condition:
106
- if not self.paused:
107
- logger.info('Pause requested.')
108
- self.paused = True
109
- if wait_resume:
110
- self.check()
111
-
112
- def request_resume(self) -> None:
113
- """
114
- 请求恢复任务。
115
-
116
- 清除暂停标志并通知所有等待的线程恢复执行。
117
- 如果任务没有暂停,此操作无效果。
118
- """
119
- with self.pause_condition:
120
- if self.paused:
121
- logger.info('Resume requested.')
122
- self.paused = False
123
- self.pause_condition.notify_all()
124
-
125
- def toggle_pause(self) -> bool:
126
- """
127
- 切换暂停/恢复状态。
128
-
129
- :returns: 操作后的暂停状态。True 表示已暂停,False 表示已恢复。
130
- """
131
- with self.pause_condition:
132
- logger.info('Pause toggled.')
133
- if self.paused:
134
- self.paused = False
135
- self.pause_condition.notify_all()
136
- return False
137
- else:
138
- self.paused = True
139
- return True
140
-
141
- def clear_interrupt(self) -> None:
142
- """
143
- 清除中断信号。
144
-
145
- 用于任务正常结束或重启时重置状态。
146
- 通常在开始新任务前调用。
147
- """
148
- self.interrupt_event.clear()
149
- logger.info('Interrupt cleared.')
150
-
151
- def reset(self) -> None:
152
- """
153
- 重置流程控制器到初始状态。
154
-
155
- 清除所有信号和状态,相当于重新创建一个新的控制器。
156
- """
157
- self.interrupt_event.clear()
158
- with self.pause_condition:
159
- if self.paused:
160
- self.paused = False
161
- self.pause_condition.notify_all()
162
- logger.info('FlowController reset.')
163
-
164
- @property
165
- def is_interrupted(self) -> bool:
166
- """
167
- 检查是否收到中断请求。
168
-
169
- :returns: True 表示已收到中断请求
170
- """
171
- return self.interrupt_event.is_set()
172
-
173
- @property
174
- def is_paused(self) -> bool:
175
- """
176
- 检查是否处于暂停状态。
177
-
178
- :returns: True 表示当前处于暂停状态
179
- """
180
- return self.paused
181
-
182
- @property
183
- def status(self) -> Literal['running', 'paused', 'interrupted']:
184
- """
185
- 获取当前状态的字符串描述。
186
-
187
- :returns: 状态描述,可能的值:'running', 'paused', 'interrupted'
188
- """
189
- if self.is_interrupted:
190
- return 'interrupted'
191
- elif self.is_paused:
192
- return 'paused'
193
- else:
194
- return 'running'
195
-
196
- def __repr__(self) -> str:
1
+ import time
2
+ import logging
3
+ import threading
4
+ from typing import Literal
5
+
6
+ logger = logging.getLogger(__name__)
7
+
8
+ class FlowController:
9
+ """
10
+ 一个用于控制任务执行流程(如停止、暂停、恢复)的类。
11
+
12
+ 这个类是线程安全的,提供了以下功能:
13
+
14
+ * 停止任务执行(通过中断信号)
15
+ * 暂停/恢复任务执行
16
+ * 可中断和可暂停的 sleep 功能
17
+ * 流程状态检查
18
+
19
+ 使用方法::
20
+
21
+ controller = FlowController()
22
+
23
+ # 在任务的关键路径上调用检查
24
+ controller.check()
25
+
26
+ # 使用可控制的 sleep
27
+ controller.sleep(1.0)
28
+
29
+ # 外部控制
30
+ controller.request_pause() # 暂停
31
+ controller.request_resume() # 恢复
32
+ controller.request_stop() # 停止
33
+ """
34
+
35
+ def __init__(self):
36
+ self.interrupt_event: threading.Event = threading.Event()
37
+ """中断事件,用于停止任务"""
38
+
39
+ self.paused: bool = False
40
+ """暂停标志"""
41
+
42
+ self.pause_condition: threading.Condition = threading.Condition()
43
+ """暂停条件变量,用于线程间同步"""
44
+
45
+ def check(self) -> None:
46
+ """
47
+ 检查当前流程状态。
48
+
49
+ 如果收到停止请求,则抛出 KeyboardInterrupt 异常。
50
+ 如果收到暂停请求,则阻塞直到恢复。
51
+
52
+ 这是核心的检查点方法,应在任务的关键路径上(如循环或等待前)调用。
53
+
54
+ :raises KeyboardInterrupt: 当收到停止请求时
55
+ """
56
+ # 优先检查中断信号
57
+ if self.interrupt_event.is_set():
58
+ raise KeyboardInterrupt("User requested interrupt.")
59
+
60
+ # 检查暂停状态
61
+ with self.pause_condition:
62
+ while self.paused:
63
+ self.pause_condition.wait()
64
+
65
+ def sleep(self, seconds: float) -> None:
66
+ """
67
+ 一个可被中断和暂停的 sleep 方法。
68
+
69
+ 与标准的 time.sleep() 不同,这个方法会响应停止和暂停请求。
70
+ 在暂停状态下,计时器会暂停,恢复后继续计时。
71
+
72
+ :param seconds: 睡眠时间(秒)
73
+ :raises KeyboardInterrupt: 当收到停止请求时
74
+ """
75
+ with self.pause_condition:
76
+ end_time = time.time() + seconds
77
+ while True:
78
+ self.check() # 每次循环都检查状态
79
+ remaining = end_time - time.time()
80
+ if remaining <= 0:
81
+ break
82
+ # 等待指定时间或直到被唤醒
83
+ self.pause_condition.wait(timeout=remaining)
84
+
85
+ # 结束后再次检查状态
86
+ self.check()
87
+
88
+ def request_interrupt(self) -> None:
89
+ """
90
+ 请求停止任务。
91
+
92
+ 设置中断信号,所有正在执行的任务将在下一个检查点停止。
93
+ 停止的优先级高于暂停。
94
+ """
95
+ logger.info('Interrupt requested.')
96
+ self.interrupt_event.set()
97
+
98
+ def request_pause(self, *, wait_resume: bool = False) -> None:
99
+ """
100
+ 请求暂停任务。
101
+
102
+ 设置暂停标志,所有正在执行的任务将在下一个检查点暂停。
103
+ 如果任务已经暂停,此操作无效果。
104
+ """
105
+ with self.pause_condition:
106
+ if not self.paused:
107
+ logger.info('Pause requested.')
108
+ self.paused = True
109
+ if wait_resume:
110
+ self.check()
111
+
112
+ def request_resume(self) -> None:
113
+ """
114
+ 请求恢复任务。
115
+
116
+ 清除暂停标志并通知所有等待的线程恢复执行。
117
+ 如果任务没有暂停,此操作无效果。
118
+ """
119
+ with self.pause_condition:
120
+ if self.paused:
121
+ logger.info('Resume requested.')
122
+ self.paused = False
123
+ self.pause_condition.notify_all()
124
+
125
+ def toggle_pause(self) -> bool:
126
+ """
127
+ 切换暂停/恢复状态。
128
+
129
+ :returns: 操作后的暂停状态。True 表示已暂停,False 表示已恢复。
130
+ """
131
+ with self.pause_condition:
132
+ logger.info('Pause toggled.')
133
+ if self.paused:
134
+ self.paused = False
135
+ self.pause_condition.notify_all()
136
+ return False
137
+ else:
138
+ self.paused = True
139
+ return True
140
+
141
+ def clear_interrupt(self) -> None:
142
+ """
143
+ 清除中断信号。
144
+
145
+ 用于任务正常结束或重启时重置状态。
146
+ 通常在开始新任务前调用。
147
+ """
148
+ self.interrupt_event.clear()
149
+ logger.info('Interrupt cleared.')
150
+
151
+ def reset(self) -> None:
152
+ """
153
+ 重置流程控制器到初始状态。
154
+
155
+ 清除所有信号和状态,相当于重新创建一个新的控制器。
156
+ """
157
+ self.interrupt_event.clear()
158
+ with self.pause_condition:
159
+ if self.paused:
160
+ self.paused = False
161
+ self.pause_condition.notify_all()
162
+ logger.info('FlowController reset.')
163
+
164
+ @property
165
+ def is_interrupted(self) -> bool:
166
+ """
167
+ 检查是否收到中断请求。
168
+
169
+ :returns: True 表示已收到中断请求
170
+ """
171
+ return self.interrupt_event.is_set()
172
+
173
+ @property
174
+ def is_paused(self) -> bool:
175
+ """
176
+ 检查是否处于暂停状态。
177
+
178
+ :returns: True 表示当前处于暂停状态
179
+ """
180
+ return self.paused
181
+
182
+ @property
183
+ def status(self) -> Literal['running', 'paused', 'interrupted']:
184
+ """
185
+ 获取当前状态的字符串描述。
186
+
187
+ :returns: 状态描述,可能的值:'running', 'paused', 'interrupted'
188
+ """
189
+ if self.is_interrupted:
190
+ return 'interrupted'
191
+ elif self.is_paused:
192
+ return 'paused'
193
+ else:
194
+ return 'running'
195
+
196
+ def __repr__(self) -> str:
197
197
  return f"FlowController(status='{self.status}')"