computer-use-ootb-internal 0.0.105__py3-none-any.whl → 0.0.107__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.
- computer_use_ootb_internal/app_teachmode.py +490 -490
- computer_use_ootb_internal/computer_use_demo/animation/click_animation.py +67 -195
- computer_use_ootb_internal/computer_use_demo/animation/test_animation.py +40 -0
- computer_use_ootb_internal/computer_use_demo/executor/teachmode_executor.py +5 -8
- computer_use_ootb_internal/computer_use_demo/gui_agent/gui_parser/simple_parser/test_capture.py +7 -7
- computer_use_ootb_internal/computer_use_demo/tools/computer.py +5 -8
- computer_use_ootb_internal/requirements-lite.txt +2 -1
- computer_use_ootb_internal/run_teachmode_ootb_args.py +3 -6
- {computer_use_ootb_internal-0.0.105.dist-info → computer_use_ootb_internal-0.0.107.dist-info}/METADATA +4 -3
- {computer_use_ootb_internal-0.0.105.dist-info → computer_use_ootb_internal-0.0.107.dist-info}/RECORD +12 -14
- computer_use_ootb_internal/example_websocket_js.html +0 -41
- computer_use_ootb_internal/service_teachmode.py +0 -194
- computer_use_ootb_internal/service_teachmode_test.py +0 -41
- {computer_use_ootb_internal-0.0.105.dist-info → computer_use_ootb_internal-0.0.107.dist-info}/WHEEL +0 -0
- {computer_use_ootb_internal-0.0.105.dist-info → computer_use_ootb_internal-0.0.107.dist-info}/entry_points.txt +0 -0
@@ -1,214 +1,86 @@
|
|
1
|
-
""
|
2
|
-
|
3
|
-
→ 在屏幕 (x,y) 显示点击动画,停留 duration_ms 毫秒
|
4
|
-
依赖: pyside6
|
5
|
-
确保同目录有 click.gif
|
6
|
-
"""
|
7
|
-
import sys, time
|
1
|
+
# click_anim_async.py ← put this in its own file (important for Windows "spawn")
|
2
|
+
import sys, multiprocessing as mp
|
8
3
|
from pathlib import Path
|
9
|
-
from PySide6.QtCore
|
10
|
-
from PySide6.QtGui
|
4
|
+
from PySide6.QtCore import Qt, QPoint, QTimer, QEasingCurve, QPropertyAnimation, QSize
|
5
|
+
from PySide6.QtGui import QMovie
|
11
6
|
from PySide6.QtWidgets import QApplication, QWidget, QLabel
|
12
7
|
|
13
8
|
CLICK_GIF = Path(__file__).with_name("icons8-select-cursor-transparent-96.gif")
|
14
9
|
|
10
|
+
# ---------------------------- tiny in‑process GUI helpers ----------------------------
|
15
11
|
class ClickAnimation(QWidget):
|
16
|
-
def __init__(self, pos: QPoint, life_ms: int):
|
12
|
+
def __init__(self, pos: QPoint, life_ms: int, size_px: int = 50):
|
17
13
|
super().__init__(None,
|
18
14
|
Qt.FramelessWindowHint | Qt.Tool | Qt.WindowStaysOnTopHint
|
19
15
|
| Qt.WindowTransparentForInput)
|
20
16
|
self.setAttribute(Qt.WA_TranslucentBackground)
|
21
|
-
|
22
|
-
if not CLICK_GIF.exists():
|
23
|
-
print(f"Error: click.gif not found at {CLICK_GIF}")
|
24
|
-
return
|
25
|
-
|
26
|
-
try:
|
27
|
-
# 创建标签显示GIF
|
28
|
-
self.label = QLabel(self)
|
29
|
-
self.movie = QMovie(str(CLICK_GIF))
|
30
|
-
|
31
|
-
# 获取原始尺寸并打印(仅供参考)
|
32
|
-
self.movie.jumpToFrame(0)
|
33
|
-
original_size = self.movie.currentPixmap().size()
|
34
|
-
print(f"GIF original size: {original_size.width()}x{original_size.height()}")
|
35
|
-
|
36
|
-
# 将GIF缩放到30x30像素
|
37
|
-
target_size = QSize(50, 50)
|
38
|
-
self.movie.setScaledSize(target_size)
|
39
|
-
|
40
|
-
# 设置标签尺寸和GIF
|
41
|
-
self.label.setMovie(self.movie)
|
42
|
-
self.label.setFixedSize(target_size)
|
43
|
-
|
44
|
-
# 设置窗口大小和位置
|
45
|
-
self.resize(target_size)
|
46
|
-
self.move(pos.x() - 15, pos.y() - 15) # 居中显示
|
47
|
-
|
48
|
-
# 提高播放性能
|
49
|
-
self.movie.setCacheMode(QMovie.CacheAll)
|
50
|
-
|
51
|
-
# 开始播放动画
|
52
|
-
self.movie.start()
|
53
|
-
|
54
|
-
# 设置定时器关闭窗口
|
55
|
-
QTimer.singleShot(life_ms, self.close)
|
56
|
-
|
57
|
-
self.show()
|
58
|
-
self.raise_()
|
59
|
-
print(f"Click animation created at ({pos.x()}, {pos.y()}), size: 30x30, duration: {life_ms}ms")
|
60
|
-
except Exception as e:
|
61
|
-
print(f"Error creating click animation: {str(e)}")
|
62
|
-
|
63
|
-
# ---------- 外部接口 ----------
|
64
|
-
_app = None
|
65
|
-
def _ensure_app():
|
66
|
-
global _app
|
67
|
-
if _app is None:
|
68
|
-
if QApplication.instance() is None:
|
69
|
-
print("Creating new QApplication instance")
|
70
|
-
_app = QApplication(sys.argv)
|
71
|
-
else:
|
72
|
-
print("Using existing QApplication instance")
|
73
|
-
_app = QApplication.instance()
|
74
|
-
|
75
|
-
# Keep references to animations to prevent garbage collection
|
76
|
-
_active_animations = []
|
77
|
-
|
78
|
-
def show_click(x: int, y: int, duration_ms: int = 2000, existing_ms: int = 2000): # 增加默认播放时间和静止时间
|
79
|
-
"""非阻塞式点击动画:立即返回,动画在后台运行
|
80
|
-
|
81
|
-
Args:
|
82
|
-
x, y : 屏幕坐标
|
83
|
-
duration_ms : 动画播放时长
|
84
|
-
existing_ms : 动画结束后静止显示的时间
|
85
|
-
"""
|
86
|
-
print(f"Attempting to show click at ({x}, {y})")
|
87
|
-
|
88
|
-
if not CLICK_GIF.exists():
|
89
|
-
raise FileNotFoundError(f"click.gif not found at {CLICK_GIF}")
|
90
|
-
|
91
|
-
_ensure_app()
|
92
|
-
|
93
|
-
try:
|
94
|
-
# 总生存时间 = 动画时间 + 静止显示时间
|
95
|
-
total_life_ms = duration_ms + existing_ms
|
96
|
-
animation = ClickAnimation(QPoint(x, y), total_life_ms)
|
97
|
-
|
98
|
-
# Store reference to prevent garbage collection
|
99
|
-
global _active_animations
|
100
|
-
_active_animations.append(animation)
|
101
|
-
|
102
|
-
# Set up cleanup after animation completes + existing time
|
103
|
-
QTimer.singleShot(total_life_ms + 150, lambda: _clean_animation(animation))
|
104
|
-
|
105
|
-
print(f"Click animation started (non-blocking, will exist for {total_life_ms}ms)")
|
106
|
-
except Exception as e:
|
107
|
-
print(f"Error during show_click: {str(e)}")
|
108
|
-
|
109
|
-
|
110
|
-
def _clean_animation(animation):
|
111
|
-
"""Remove animation from reference list after it completes"""
|
112
|
-
global _active_animations
|
113
|
-
if animation in _active_animations:
|
114
|
-
_active_animations.remove(animation)
|
115
|
-
print("Animation cleaned up")
|
116
|
-
|
117
|
-
|
118
|
-
# ---------- 新增函数 ----------
|
119
|
-
def show_move_to(x1: int, y1: int, x2: int, y2: int, duration_ms: int = 1000, existing_ms: int = 3000):
|
120
|
-
"""
|
121
|
-
非阻塞式移动动画:在 (x1, y1) 处出现光标 GIF,
|
122
|
-
并在 duration_ms 毫秒内平滑移动到 (x2, y2),
|
123
|
-
然后在终点静止显示 existing_ms 毫秒。
|
124
|
-
立即返回,动画在后台运行。
|
125
|
-
|
126
|
-
Args:
|
127
|
-
x1, y1 : 起点屏幕坐标
|
128
|
-
x2, y2 : 终点屏幕坐标
|
129
|
-
duration_ms : 移动总时长
|
130
|
-
existing_ms : 移动结束后在终点静止显示的时间
|
131
|
-
"""
|
132
|
-
print(f"Attempting to move click from ({x1}, {y1}) → ({x2}, {y2}) "
|
133
|
-
f"in {duration_ms} ms, then stay for {existing_ms} ms")
|
134
17
|
|
135
|
-
|
136
|
-
|
18
|
+
self.label = QLabel(self)
|
19
|
+
movie = QMovie(str(CLICK_GIF))
|
20
|
+
movie.setScaledSize(QSize(size_px, size_px))
|
21
|
+
self.label.setMovie(movie)
|
22
|
+
self.label.setFixedSize(size_px, size_px)
|
23
|
+
|
24
|
+
self.resize(size_px, size_px)
|
25
|
+
self.move(pos.x() - size_px//2, pos.y() - size_px//2)
|
26
|
+
|
27
|
+
movie.setCacheMode(QMovie.CacheAll)
|
28
|
+
movie.start()
|
29
|
+
QTimer.singleShot(life_ms, self.close)
|
30
|
+
self.show()
|
31
|
+
self.raise_()
|
137
32
|
|
138
|
-
|
33
|
+
# ------------------------- worker functions that live in a **child** -----------------
|
34
|
+
def _worker_click(x, y, duration_ms, existing_ms):
|
35
|
+
app = QApplication(sys.argv)
|
36
|
+
total = duration_ms + existing_ms
|
37
|
+
widget = ClickAnimation(QPoint(x, y), total) # Store in variable to prevent garbage collection
|
38
|
+
QTimer.singleShot(total + 200, app.quit) # close event‑loop afterwards
|
39
|
+
app.exec()
|
40
|
+
|
41
|
+
def _worker_move(x1, y1, x2, y2, duration_ms, existing_ms):
|
42
|
+
app = QApplication(sys.argv)
|
43
|
+
total = duration_ms + existing_ms
|
44
|
+
widget = ClickAnimation(QPoint(x1, y1), total)
|
139
45
|
|
140
|
-
# 总生存时间 = 动画时间 + 静止显示时间
|
141
|
-
total_life_ms = duration_ms + existing_ms
|
142
|
-
widget = ClickAnimation(QPoint(x1, y1), total_life_ms)
|
143
|
-
|
144
|
-
# 用 QPropertyAnimation 平滑移动窗口
|
145
46
|
anim = QPropertyAnimation(widget, b"pos")
|
146
47
|
anim.setDuration(duration_ms)
|
147
|
-
|
148
|
-
anim.
|
149
|
-
anim.
|
150
|
-
anim.setEasingCurve(QEasingCurve.OutQuad) # 可自行更换缓动曲线
|
151
|
-
|
152
|
-
# Store references to both widget and animation to prevent garbage collection
|
153
|
-
global _active_animations
|
154
|
-
# Store them as a tuple to keep both references
|
155
|
-
animation_pair = (widget, anim)
|
156
|
-
_active_animations.append(animation_pair)
|
157
|
-
|
158
|
-
# Clean up both widget and animation after completion of total life time
|
159
|
-
def cleanup():
|
160
|
-
if animation_pair in _active_animations:
|
161
|
-
_active_animations.remove(animation_pair)
|
162
|
-
print("Move animation cleaned up")
|
163
|
-
|
164
|
-
# Connect finished signal only to print a message
|
165
|
-
anim.finished.connect(lambda: print("Movement finished, now staying still"))
|
166
|
-
|
167
|
-
# Start the animation
|
48
|
+
anim.setStartValue(widget.pos())
|
49
|
+
anim.setEndValue(QPoint(x2 - widget.width()//2, y2 - widget.height()//2))
|
50
|
+
anim.setEasingCurve(QEasingCurve.OutQuad)
|
168
51
|
anim.start()
|
169
|
-
|
170
|
-
|
171
|
-
|
172
|
-
|
173
|
-
|
174
|
-
|
175
|
-
|
176
|
-
|
52
|
+
|
53
|
+
QTimer.singleShot(total + 200, app.quit)
|
54
|
+
app.exec()
|
55
|
+
|
56
|
+
# ------------------------------- public API (non‑blocking) ---------------------------
|
57
|
+
def show_click(x: int, y: int, duration_ms: int = 800, existing_ms: int = 800):
|
58
|
+
if not CLICK_GIF.exists():
|
59
|
+
raise FileNotFoundError(f"GIF not found at {CLICK_GIF}")
|
60
|
+
mp.get_context("spawn").Process(
|
61
|
+
target=_worker_click,
|
62
|
+
args=(x, y, duration_ms, existing_ms),
|
63
|
+
daemon=False # keep running even if parent exits
|
64
|
+
).start()
|
65
|
+
|
66
|
+
def show_move_to(x1: int, y1: int, x2: int, y2: int,
|
67
|
+
duration_ms: int = 1000, existing_ms: int = 800):
|
68
|
+
if not CLICK_GIF.exists():
|
69
|
+
raise FileNotFoundError(f"GIF not found at {CLICK_GIF}")
|
70
|
+
mp.get_context("spawn").Process(
|
71
|
+
target=_worker_move,
|
72
|
+
args=(x1, y1, x2, y2, duration_ms, existing_ms),
|
73
|
+
daemon=False
|
74
|
+
).start()
|
75
|
+
|
177
76
|
|
178
77
|
|
179
|
-
# ---------- 命令行测试 ----------
|
180
78
|
if __name__ == "__main__":
|
181
|
-
#
|
182
|
-
|
183
|
-
|
184
|
-
|
185
|
-
|
186
|
-
x, y
|
187
|
-
|
188
|
-
|
189
|
-
# 测试同时运行两个动画
|
190
|
-
print("\nTesting simultaneous animations...")
|
191
|
-
x1, y1 = 200, 200
|
192
|
-
x2, y2 = 600, 600
|
193
|
-
# show_click(x1, y1)
|
194
|
-
show_move_to(x1, y1, x2, y2, duration_ms=2000)
|
195
|
-
|
196
|
-
# # 测试先移动,然后点击
|
197
|
-
print("\nTesting sequence with pyautogui simulation...")
|
198
|
-
x3, y3 = 800, 300
|
199
|
-
x4, y4 = 400, 500
|
200
|
-
|
201
|
-
# 启动移动动画
|
202
|
-
show_move_to(x3, y3, x4, y4, duration_ms=1500)
|
203
|
-
|
204
|
-
# 模拟移动完成后的点击动画(延迟1.5秒)
|
205
|
-
QTimer.singleShot(1500, lambda: show_click(x4, y4))
|
206
|
-
|
207
|
-
# 保持主程序运行,等待所有动画完成
|
208
|
-
print("\nWaiting for all animations to complete...")
|
209
|
-
loop = QEventLoop()
|
210
|
-
# 等待足够长的时间,确保所有动画都完成(最长的动画是2000ms + 清理时间)
|
211
|
-
QTimer.singleShot(4000, loop.quit)
|
212
|
-
loop.exec()
|
213
|
-
|
214
|
-
print("All animations completed, exiting test.")
|
79
|
+
# from click_anim_async import show_click
|
80
|
+
|
81
|
+
import pyautogui
|
82
|
+
x, y = pyautogui.position()
|
83
|
+
|
84
|
+
show_move_to(x, y, 600, 600)
|
85
|
+
|
86
|
+
show_click(600, 600)
|
@@ -0,0 +1,40 @@
|
|
1
|
+
"""
|
2
|
+
Test script to verify cursor animation is working
|
3
|
+
"""
|
4
|
+
import asyncio
|
5
|
+
import sys
|
6
|
+
import time
|
7
|
+
from pathlib import Path
|
8
|
+
from computer_use_ootb_internal.computer_use_demo.tools.computer import ComputerTool
|
9
|
+
|
10
|
+
async def test_animations():
|
11
|
+
|
12
|
+
# Initialize the computer tool
|
13
|
+
computer = ComputerTool()
|
14
|
+
|
15
|
+
# Test mouse move animation
|
16
|
+
print("Testing mouse move animation...")
|
17
|
+
await computer(action="mouse_move_windll", coordinate=(500, 500))
|
18
|
+
print("Waiting 2 seconds...")
|
19
|
+
await asyncio.sleep(2)
|
20
|
+
|
21
|
+
# Test click animation
|
22
|
+
print("Testing click animation...")
|
23
|
+
await computer(action="left_click_windll", coordinate=(700, 300))
|
24
|
+
print("Waiting 2 seconds...")
|
25
|
+
await asyncio.sleep(2)
|
26
|
+
|
27
|
+
# Test another move
|
28
|
+
print("Testing move and click sequence...")
|
29
|
+
await computer(action="mouse_move_windll", coordinate=(300, 300))
|
30
|
+
await asyncio.sleep(1)
|
31
|
+
await computer(action="left_click_windll", coordinate=(300, 300))
|
32
|
+
|
33
|
+
# Wait for animations to complete
|
34
|
+
print("Waiting for animations to complete...")
|
35
|
+
await asyncio.sleep(3)
|
36
|
+
|
37
|
+
print("Test completed")
|
38
|
+
|
39
|
+
if __name__ == "__main__":
|
40
|
+
asyncio.run(test_animations())
|
@@ -146,12 +146,12 @@ class TeachmodeExecutor:
|
|
146
146
|
else:
|
147
147
|
raise ValueError(f"Input action {action_item['action']} does not contain 'text' or 'value'.")
|
148
148
|
|
149
|
-
elif action_item["action"]
|
149
|
+
elif action_item["action"] in ["ENTER", "RETURN"] \
|
150
|
+
or (action_item["action"] == "KEY" and action_item["value"] in ["ENTER", "RETURN"]): # 3. enter -> key, enter
|
150
151
|
refined_output.append({"action": "key", "text": "Enter", "coordinate": None})
|
151
152
|
|
152
|
-
elif action_item["action"]
|
153
|
-
or action_item["action"] == "ESCAPE"
|
154
|
-
or (action_item["action"] == "KEY" and action_item["value"] == "ESC"): # 4. enter -> key, enter
|
153
|
+
elif action_item["action"] in ["ESCAPE", "ESC"] \
|
154
|
+
or (action_item["action"] == "KEY" and action_item["value"] in ["ESC", "ESCAPE"]): # 4. enter -> key, enter
|
155
155
|
refined_output.append({"action": "key", "text": "Escape", "coordinate": None})
|
156
156
|
|
157
157
|
elif action_item["action"] == "HOVER" or action_item["action"] == "MOVE": # 5. hover -> mouse_move
|
@@ -177,7 +177,7 @@ class TeachmodeExecutor:
|
|
177
177
|
refined_output.append({"action": "mouse_move", "text": None, "coordinate": tuple(action_item["position"])})
|
178
178
|
refined_output.append({"action": "left_press", "text": None, "coordinate": None})
|
179
179
|
|
180
|
-
elif action_item["action"]
|
180
|
+
elif action_item["action"] in ["HOTKEY", "KEY"]: # 8. hotkey
|
181
181
|
refined_output.append({"action": "key", "text": action_item["value"], "coordinate": None})
|
182
182
|
|
183
183
|
elif action_item["action"] == "DRAG": # 9. drag
|
@@ -249,9 +249,6 @@ class TeachmodeExecutor:
|
|
249
249
|
else:
|
250
250
|
parsed_action_list.append(action)
|
251
251
|
|
252
|
-
# parsed_action_list.extend([{"action": "key_down_windll", "text": "alt", "coordinate": None}])
|
253
|
-
# parsed_action_list.extend(action_list)
|
254
|
-
# parsed_action_list.extend([{"action": "key_up_windll", "text": "alt", "coordinate": None}])
|
255
252
|
return parsed_action_list
|
256
253
|
|
257
254
|
|
computer_use_ootb_internal/computer_use_demo/gui_agent/gui_parser/simple_parser/test_capture.py
CHANGED
@@ -1,8 +1,8 @@
|
|
1
|
-
from PIL import ImageGrab
|
2
|
-
|
3
|
-
bbox=(2560, 366, 2560+1920, 366+1080)
|
4
|
-
|
5
|
-
screenshot = ImageGrab.grab(bbox=bbox, all_screens=True)
|
6
|
-
|
7
|
-
screenshot = screenshot.convert('RGB')
|
1
|
+
from PIL import ImageGrab
|
2
|
+
|
3
|
+
bbox=(2560, 366, 2560+1920, 366+1080)
|
4
|
+
|
5
|
+
screenshot = ImageGrab.grab(bbox=bbox, all_screens=True)
|
6
|
+
|
7
|
+
screenshot = screenshot.convert('RGB')
|
8
8
|
screenshot.save("screenshot.png")
|
@@ -317,7 +317,6 @@ class ComputerTool(BaseAnthropicTool):
|
|
317
317
|
pyautogui.mouseDown()
|
318
318
|
time.sleep(1)
|
319
319
|
pyautogui.mouseUp()
|
320
|
-
show_click(x, y)
|
321
320
|
elif action == "scroll_down":
|
322
321
|
pyautogui.scroll(-200) # Adjust scroll amount as needed
|
323
322
|
return ToolResult(output="Scrolled down")
|
@@ -327,7 +326,7 @@ class ComputerTool(BaseAnthropicTool):
|
|
327
326
|
return ToolResult(output="Scrolled up")
|
328
327
|
|
329
328
|
elif action == "wait":
|
330
|
-
time.sleep(
|
329
|
+
time.sleep(15)
|
331
330
|
return ToolResult(output="Waited")
|
332
331
|
|
333
332
|
return ToolResult(output=f"Performed {action}")
|
@@ -375,9 +374,11 @@ class ComputerTool(BaseAnthropicTool):
|
|
375
374
|
y = coordinate[1]+self.offset_y
|
376
375
|
show_click(x, y)
|
377
376
|
self.marbot_auto_gui.click(x=x, y=y)
|
377
|
+
|
378
378
|
elif action == "mouse_move_windll":
|
379
379
|
if coordinate is None:
|
380
380
|
raise ToolError(f"coordinate is required for {action}")
|
381
|
+
|
381
382
|
x0, y0 = pyautogui.position()
|
382
383
|
# x0, y0 = self.scale_coordinates(ScalingSource.COMPUTER, x0, y0)
|
383
384
|
x1 = coordinate[0]+self.offset_x
|
@@ -614,15 +615,11 @@ class ComputerTool(BaseAnthropicTool):
|
|
614
615
|
# Adjust for different coordinate system
|
615
616
|
return int(loc.x), int(self.height - loc.y)
|
616
617
|
|
617
|
-
def map_keys(self, text: str):
|
618
|
-
"""Map text to cliclick key codes if necessary."""
|
619
|
-
# For simplicity, return text as is
|
620
|
-
# Implement mapping if special keys are needed
|
621
|
-
return text
|
622
618
|
|
623
619
|
|
624
620
|
if __name__ == "__main__":
|
625
621
|
computer = ComputerTool()
|
626
622
|
# test left_click_windll
|
627
623
|
# asyncio.run(computer(action="left_click_windll", coordinate=(500, 500)))
|
628
|
-
asyncio.run(computer(action="mouse_move_windll", coordinate=(500, 500)))
|
624
|
+
asyncio.run(computer(action="mouse_move_windll", coordinate=(500, 500)))
|
625
|
+
asyncio.run(computer(action="left_click_windll", coordinate=(500, 500)))
|
@@ -41,7 +41,7 @@ def simple_teachmode_sampling_loop(
|
|
41
41
|
if "star_rail" in user_id or "star_rail" in user_id:
|
42
42
|
full_screen_game_mode = 1
|
43
43
|
|
44
|
-
if "star_rail_dev" in trace_id or "star_rail_dev" in user_id or "hero_case" in
|
44
|
+
if "star_rail_dev" in trace_id or "star_rail_dev" in user_id or "hero_case" in user_id:
|
45
45
|
full_screen_game_mode = 2
|
46
46
|
|
47
47
|
print(f"Full Screen Game Mode: {full_screen_game_mode}")
|
@@ -102,7 +102,7 @@ def simple_teachmode_sampling_loop(
|
|
102
102
|
|
103
103
|
try:
|
104
104
|
step_plan = infer_server_response["generated_plan"]
|
105
|
-
step_info = infer_server_response["
|
105
|
+
step_info = infer_server_response["generated_plan"]["step_info"]
|
106
106
|
step_action = infer_server_response["generated_action"]["content"]
|
107
107
|
step_traj_idx = infer_server_response["current_traj_step"]
|
108
108
|
|
@@ -112,6 +112,7 @@ def simple_teachmode_sampling_loop(
|
|
112
112
|
|
113
113
|
if step_action.get("action") == "STOP":
|
114
114
|
final_sc, final_sc_path = get_screenshot_external_cmd(selected_screen=selected_screen)
|
115
|
+
action_history = [] # reset action history
|
115
116
|
break
|
116
117
|
|
117
118
|
# action_history.append(f"Executing Step: {step_count} - Trajectory Step: {step_traj_idx} - Plan: {step_plan} - Action: {step_action};\n")
|
@@ -125,8 +126,6 @@ def simple_teachmode_sampling_loop(
|
|
125
126
|
|
126
127
|
|
127
128
|
|
128
|
-
|
129
|
-
|
130
129
|
if __name__ == "__main__":
|
131
130
|
parser = argparse.ArgumentParser(
|
132
131
|
description="Run a synchronous sampling loop for assistant/tool interactions in teach-mode."
|
@@ -138,8 +137,6 @@ if __name__ == "__main__":
|
|
138
137
|
)
|
139
138
|
parser.add_argument(
|
140
139
|
"--task",
|
141
|
-
# default="Help me to complete the extraction of the viewer data of Downald Trump's first video on youtube,\
|
142
|
-
# fill in the excel sheet.",
|
143
140
|
default="Click on the Google Chorme icon",
|
144
141
|
help="The task to be completed by the assistant (e.g., 'Complete some data extraction.').",
|
145
142
|
)
|
@@ -1,6 +1,6 @@
|
|
1
1
|
Metadata-Version: 2.4
|
2
2
|
Name: computer-use-ootb-internal
|
3
|
-
Version: 0.0.
|
3
|
+
Version: 0.0.107
|
4
4
|
Summary: Computer Use OOTB
|
5
5
|
Author-email: Siyuan Hu <siyuan.hu.sg@gmail.com>
|
6
6
|
Requires-Python: >=3.11
|
@@ -14,14 +14,15 @@ Requires-Dist: matplotlib
|
|
14
14
|
Requires-Dist: opencv-python
|
15
15
|
Requires-Dist: pre-commit==3.8.0
|
16
16
|
Requires-Dist: pyautogui==0.9.54
|
17
|
+
Requires-Dist: pyside6
|
17
18
|
Requires-Dist: pytest-asyncio==0.23.6
|
18
19
|
Requires-Dist: pytest==8.3.3
|
19
|
-
Requires-Dist: pywinauto
|
20
|
+
Requires-Dist: pywinauto
|
20
21
|
Requires-Dist: ruff==0.6.7
|
21
22
|
Requires-Dist: screeninfo
|
22
23
|
Requires-Dist: streamlit>=1.38.0
|
23
24
|
Requires-Dist: textdistance
|
24
|
-
Requires-Dist: uiautomation
|
25
|
+
Requires-Dist: uiautomation
|
25
26
|
Provides-Extra: dev
|
26
27
|
Requires-Dist: pytest-asyncio>=0.23.6; extra == 'dev'
|
27
28
|
Requires-Dist: pytest>=8.3.3; extra == 'dev'
|
{computer_use_ootb_internal-0.0.105.dist-info → computer_use_ootb_internal-0.0.107.dist-info}/RECORD
RENAMED
@@ -1,19 +1,17 @@
|
|
1
1
|
computer_use_ootb_internal/README.md,sha256=FxpW95lyub2iX73ZDfK6ML7SdEKg060H5I6Grub7li4,31
|
2
|
-
computer_use_ootb_internal/app_teachmode.py,sha256=
|
2
|
+
computer_use_ootb_internal/app_teachmode.py,sha256=CyNUk9AqbmBtOvYsEHG16wBH6F-Vje3CiMPnJ9oB-b8,19549
|
3
3
|
computer_use_ootb_internal/app_teachmode_gradio.py,sha256=zAw-n3s20j1Jr0S4TzXHwllKV6APJ8HEHB1KqBuzriY,7907
|
4
4
|
computer_use_ootb_internal/dependency_check.py,sha256=y8RMEP6RXQzTgU1MS_1piBLtz4J-Hfn9RjUZg59dyvo,1333
|
5
|
-
computer_use_ootb_internal/
|
6
|
-
computer_use_ootb_internal/
|
7
|
-
computer_use_ootb_internal/
|
8
|
-
computer_use_ootb_internal/service_teachmode.py,sha256=e81zp3B7CA2nMjA-3qoKF4P1hlNGRI7P1tBo1j21FBk,8082
|
9
|
-
computer_use_ootb_internal/service_teachmode_test.py,sha256=zpfBFFKD9WGLX4m77ajOBfmczpYsCa3_qTBweeSNRV8,1112
|
10
|
-
computer_use_ootb_internal/computer_use_demo/animation/click_animation.py,sha256=j3v-CrFp61mZiJ4-eT06txkOoguZipbakrQFj2d_mbk,7759
|
5
|
+
computer_use_ootb_internal/requirements-lite.txt,sha256=5DAHomz4A_P2BmTIXNkNqkHbnIF0AyZ4_1XAlb1LaYs,290
|
6
|
+
computer_use_ootb_internal/run_teachmode_ootb_args.py,sha256=NZ6EcSIw8mXKFLWwaqANNyMyO3Vz5SS7r5irCJyyOSM,6742
|
7
|
+
computer_use_ootb_internal/computer_use_demo/animation/click_animation.py,sha256=99Ehm7HKXCYqLhE3KgdyRcilF3K4dMycKZ14l-CB3_I,3235
|
11
8
|
computer_use_ootb_internal/computer_use_demo/animation/icons8-select-cursor-transparent-96.gif,sha256=4LfwsfFQnREXrNRs32aJU2jO65JXianJoL_8q7-8elg,30966
|
12
|
-
computer_use_ootb_internal/computer_use_demo/
|
9
|
+
computer_use_ootb_internal/computer_use_demo/animation/test_animation.py,sha256=SOJz2yffXTkjuAHqk0IZLcMriR0KQYTo7W1b8wGyRGY,1222
|
10
|
+
computer_use_ootb_internal/computer_use_demo/executor/teachmode_executor.py,sha256=3IwTm99UUzQ7NLpt4r2g2iiluXWzdn8n4hCwy2XWP78,16426
|
13
11
|
computer_use_ootb_internal/computer_use_demo/gui_agent/gui_parser/simple_parser/__init__.py,sha256=h2CNeuACklxVpJC65QR8_6AvSybEZLmeO45hY_-lLBs,61
|
14
12
|
computer_use_ootb_internal/computer_use_demo/gui_agent/gui_parser/simple_parser/gui_capture.py,sha256=CxFJbsSb68ERKH7-C4RaaZy7FIhhzrzGx5qQJ4C37cA,13907
|
15
13
|
computer_use_ootb_internal/computer_use_demo/gui_agent/gui_parser/simple_parser/gui_parser.py,sha256=KSTJ0cMwh3ahUMzHRaDgA2sVNUL4MNlF7qEBGN3G0SI,28993
|
16
|
-
computer_use_ootb_internal/computer_use_demo/gui_agent/gui_parser/simple_parser/test_capture.py,sha256=
|
14
|
+
computer_use_ootb_internal/computer_use_demo/gui_agent/gui_parser/simple_parser/test_capture.py,sha256=26uxu70di9Me-jseym5ejF7RNIbP35uPEiipN5qamIc,211
|
17
15
|
computer_use_ootb_internal/computer_use_demo/gui_agent/gui_parser/simple_parser/uia_parser.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
18
16
|
computer_use_ootb_internal/computer_use_demo/gui_agent/gui_parser/simple_parser/utils.py,sha256=GEA1ES7vOpHBg_Suxpl99reh34kRG4RQpp072JQBK5c,9787
|
19
17
|
computer_use_ootb_internal/computer_use_demo/gui_agent/gui_parser/simple_parser/icon_detection/icon_detection.py,sha256=ysTgvtjE1XM7QSrLLy1HD0i6_7iOb9GME5FWJljrJg0,9752
|
@@ -33,12 +31,12 @@ computer_use_ootb_internal/computer_use_demo/tools/base.py,sha256=QDqpuuKlhUKJT2
|
|
33
31
|
computer_use_ootb_internal/computer_use_demo/tools/bash.py,sha256=rHetQ80_v-TTi-1oxIA7ncFEwJxFTh8FJCErIoZbGeY,4236
|
34
32
|
computer_use_ootb_internal/computer_use_demo/tools/collection.py,sha256=8RzHLobL44_Jjt8ltXS6I8XJlEAQOfc75dmnDUaHE-8,922
|
35
33
|
computer_use_ootb_internal/computer_use_demo/tools/colorful_text.py,sha256=cvlmnhAImDTwoRRwhT5au7mNFhfAD7ZfeoDEVdVzDKw,892
|
36
|
-
computer_use_ootb_internal/computer_use_demo/tools/computer.py,sha256=
|
34
|
+
computer_use_ootb_internal/computer_use_demo/tools/computer.py,sha256=nGHrwF60nExw6pVhs_gThr5pSObVv_yE-RYPbkGPG6U,25375
|
37
35
|
computer_use_ootb_internal/computer_use_demo/tools/computer_marbot.py,sha256=zZuWz9ArfP3Zss-afnscrPkgCtB5UWbCy7HwAOvO2bo,5970
|
38
36
|
computer_use_ootb_internal/computer_use_demo/tools/edit.py,sha256=b0PwUitxckHCQqFP3ZwlthWdqNkn7WETeTHeB6-o98c,11486
|
39
37
|
computer_use_ootb_internal/computer_use_demo/tools/run.py,sha256=xhXdnBK1di9muaO44CEirL9hpGy3NmKbjfMpyeVmn8Y,1595
|
40
38
|
computer_use_ootb_internal/computer_use_demo/tools/screen_capture.py,sha256=L8qfvtUkPPQGt92N-2Zfw5ZTDBzLsDps39uMnX3_uSA,6857
|
41
|
-
computer_use_ootb_internal-0.0.
|
42
|
-
computer_use_ootb_internal-0.0.
|
43
|
-
computer_use_ootb_internal-0.0.
|
44
|
-
computer_use_ootb_internal-0.0.
|
39
|
+
computer_use_ootb_internal-0.0.107.dist-info/METADATA,sha256=o7nhTe06oTMzWuSueoiLI5F6VZq2FobcuNue4QR6dQw,910
|
40
|
+
computer_use_ootb_internal-0.0.107.dist-info/WHEEL,sha256=qtCwoSJWgHk21S1Kb4ihdzI2rlJ1ZKaIurTj_ngOhyQ,87
|
41
|
+
computer_use_ootb_internal-0.0.107.dist-info/entry_points.txt,sha256=-AbmawU7IRQuDZihgVMVDrFoY4E6rnXYOUB-5vSeBKs,93
|
42
|
+
computer_use_ootb_internal-0.0.107.dist-info/RECORD,,
|
@@ -1,41 +0,0 @@
|
|
1
|
-
<!DOCTYPE html>
|
2
|
-
<html>
|
3
|
-
<head>
|
4
|
-
<title>Teachmode Client</title>
|
5
|
-
<!-- include socket.io client -->
|
6
|
-
<script src="https://cdn.socket.io/4.5.4/socket.io.min.js"></script>
|
7
|
-
</head>
|
8
|
-
<body>
|
9
|
-
<h1>Teachmode WebSocket Test</h1>
|
10
|
-
<div id="messages"></div>
|
11
|
-
|
12
|
-
<script>
|
13
|
-
const socket = io("http://localhost:5000"); // Your server’s URL/port
|
14
|
-
|
15
|
-
// Listen for partial responses
|
16
|
-
socket.on("partial_response", (data) => {
|
17
|
-
console.log("Got partial:", data);
|
18
|
-
const div = document.createElement("div");
|
19
|
-
div.innerText = "Assistant: " + data.content;
|
20
|
-
document.getElementById("messages").appendChild(div);
|
21
|
-
});
|
22
|
-
|
23
|
-
// Listen for done event
|
24
|
-
socket.on("done", (data) => {
|
25
|
-
console.log("Task completed:", data);
|
26
|
-
const div = document.createElement("div");
|
27
|
-
div.innerText = "TASK DONE!";
|
28
|
-
document.getElementById("messages").appendChild(div);
|
29
|
-
});
|
30
|
-
|
31
|
-
// When connected, emit run_teachmode
|
32
|
-
socket.on("connect", () => {
|
33
|
-
console.log("Connected to server. Emitting run_teachmode event...");
|
34
|
-
socket.emit("run_teachmode", {
|
35
|
-
user_input: "Hello, I'd like to do X, Y, Z."
|
36
|
-
// you can include model, task, user_id, trace_id, etc. if desired
|
37
|
-
});
|
38
|
-
});
|
39
|
-
</script>
|
40
|
-
</body>
|
41
|
-
</html>
|