hud-python 0.3.5__py3-none-any.whl → 0.4.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.

Potentially problematic release.


This version of hud-python might be problematic. Click here for more details.

Files changed (192) hide show
  1. hud/__init__.py +22 -89
  2. hud/agents/__init__.py +17 -0
  3. hud/agents/art.py +101 -0
  4. hud/agents/base.py +599 -0
  5. hud/{mcp → agents}/claude.py +373 -321
  6. hud/{mcp → agents}/langchain.py +250 -250
  7. hud/agents/misc/__init__.py +7 -0
  8. hud/{agent → agents}/misc/response_agent.py +80 -80
  9. hud/{mcp → agents}/openai.py +352 -334
  10. hud/agents/openai_chat_generic.py +154 -0
  11. hud/{mcp → agents}/tests/__init__.py +1 -1
  12. hud/agents/tests/test_base.py +742 -0
  13. hud/agents/tests/test_claude.py +324 -0
  14. hud/{mcp → agents}/tests/test_client.py +363 -324
  15. hud/{mcp → agents}/tests/test_openai.py +237 -238
  16. hud/cli/__init__.py +617 -0
  17. hud/cli/__main__.py +8 -0
  18. hud/cli/analyze.py +371 -0
  19. hud/cli/analyze_metadata.py +230 -0
  20. hud/cli/build.py +427 -0
  21. hud/cli/clone.py +185 -0
  22. hud/cli/cursor.py +92 -0
  23. hud/cli/debug.py +392 -0
  24. hud/cli/docker_utils.py +83 -0
  25. hud/cli/init.py +281 -0
  26. hud/cli/interactive.py +353 -0
  27. hud/cli/mcp_server.py +756 -0
  28. hud/cli/pull.py +336 -0
  29. hud/cli/push.py +379 -0
  30. hud/cli/remote_runner.py +311 -0
  31. hud/cli/runner.py +160 -0
  32. hud/cli/tests/__init__.py +3 -0
  33. hud/cli/tests/test_analyze.py +284 -0
  34. hud/cli/tests/test_cli_init.py +265 -0
  35. hud/cli/tests/test_cli_main.py +27 -0
  36. hud/cli/tests/test_clone.py +142 -0
  37. hud/cli/tests/test_cursor.py +253 -0
  38. hud/cli/tests/test_debug.py +453 -0
  39. hud/cli/tests/test_mcp_server.py +139 -0
  40. hud/cli/tests/test_utils.py +388 -0
  41. hud/cli/utils.py +263 -0
  42. hud/clients/README.md +143 -0
  43. hud/clients/__init__.py +16 -0
  44. hud/clients/base.py +354 -0
  45. hud/clients/fastmcp.py +202 -0
  46. hud/clients/mcp_use.py +278 -0
  47. hud/clients/tests/__init__.py +1 -0
  48. hud/clients/tests/test_client_integration.py +111 -0
  49. hud/clients/tests/test_fastmcp.py +342 -0
  50. hud/clients/tests/test_protocol.py +188 -0
  51. hud/clients/utils/__init__.py +1 -0
  52. hud/clients/utils/retry_transport.py +160 -0
  53. hud/datasets.py +322 -192
  54. hud/misc/__init__.py +1 -0
  55. hud/{agent → misc}/claude_plays_pokemon.py +292 -283
  56. hud/otel/__init__.py +35 -0
  57. hud/otel/collector.py +142 -0
  58. hud/otel/config.py +164 -0
  59. hud/otel/context.py +536 -0
  60. hud/otel/exporters.py +366 -0
  61. hud/otel/instrumentation.py +97 -0
  62. hud/otel/processors.py +118 -0
  63. hud/otel/tests/__init__.py +1 -0
  64. hud/otel/tests/test_processors.py +197 -0
  65. hud/server/__init__.py +5 -5
  66. hud/server/context.py +114 -0
  67. hud/server/helper/__init__.py +5 -0
  68. hud/server/low_level.py +132 -0
  69. hud/server/server.py +166 -0
  70. hud/server/tests/__init__.py +3 -0
  71. hud/settings.py +73 -79
  72. hud/shared/__init__.py +5 -0
  73. hud/{exceptions.py → shared/exceptions.py} +180 -180
  74. hud/{server → shared}/requests.py +264 -264
  75. hud/shared/tests/test_exceptions.py +157 -0
  76. hud/{server → shared}/tests/test_requests.py +275 -275
  77. hud/telemetry/__init__.py +25 -30
  78. hud/telemetry/instrument.py +379 -0
  79. hud/telemetry/job.py +309 -141
  80. hud/telemetry/replay.py +74 -0
  81. hud/telemetry/trace.py +83 -0
  82. hud/tools/__init__.py +33 -34
  83. hud/tools/base.py +365 -65
  84. hud/tools/bash.py +161 -137
  85. hud/tools/computer/__init__.py +15 -13
  86. hud/tools/computer/anthropic.py +437 -420
  87. hud/tools/computer/hud.py +376 -334
  88. hud/tools/computer/openai.py +295 -292
  89. hud/tools/computer/settings.py +82 -0
  90. hud/tools/edit.py +314 -290
  91. hud/tools/executors/__init__.py +30 -30
  92. hud/tools/executors/base.py +539 -532
  93. hud/tools/executors/pyautogui.py +621 -619
  94. hud/tools/executors/tests/__init__.py +1 -1
  95. hud/tools/executors/tests/test_base_executor.py +338 -338
  96. hud/tools/executors/tests/test_pyautogui_executor.py +165 -165
  97. hud/tools/executors/xdo.py +511 -503
  98. hud/tools/{playwright_tool.py → playwright.py} +412 -379
  99. hud/tools/tests/__init__.py +3 -3
  100. hud/tools/tests/test_base.py +282 -0
  101. hud/tools/tests/test_bash.py +158 -152
  102. hud/tools/tests/test_bash_extended.py +197 -0
  103. hud/tools/tests/test_computer.py +425 -52
  104. hud/tools/tests/test_computer_actions.py +34 -34
  105. hud/tools/tests/test_edit.py +259 -240
  106. hud/tools/tests/test_init.py +27 -27
  107. hud/tools/tests/test_playwright_tool.py +183 -183
  108. hud/tools/tests/test_tools.py +145 -157
  109. hud/tools/tests/test_utils.py +156 -156
  110. hud/tools/types.py +72 -0
  111. hud/tools/utils.py +50 -50
  112. hud/types.py +136 -89
  113. hud/utils/__init__.py +10 -16
  114. hud/utils/async_utils.py +65 -0
  115. hud/utils/design.py +168 -0
  116. hud/utils/mcp.py +55 -0
  117. hud/utils/progress.py +149 -149
  118. hud/utils/telemetry.py +66 -66
  119. hud/utils/tests/test_async_utils.py +173 -0
  120. hud/utils/tests/test_init.py +17 -21
  121. hud/utils/tests/test_progress.py +261 -225
  122. hud/utils/tests/test_telemetry.py +82 -37
  123. hud/utils/tests/test_version.py +8 -8
  124. hud/version.py +7 -7
  125. hud_python-0.4.0.dist-info/METADATA +474 -0
  126. hud_python-0.4.0.dist-info/RECORD +132 -0
  127. hud_python-0.4.0.dist-info/entry_points.txt +3 -0
  128. {hud_python-0.3.5.dist-info → hud_python-0.4.0.dist-info}/licenses/LICENSE +21 -21
  129. hud/adapters/__init__.py +0 -8
  130. hud/adapters/claude/__init__.py +0 -5
  131. hud/adapters/claude/adapter.py +0 -180
  132. hud/adapters/claude/tests/__init__.py +0 -1
  133. hud/adapters/claude/tests/test_adapter.py +0 -519
  134. hud/adapters/common/__init__.py +0 -6
  135. hud/adapters/common/adapter.py +0 -178
  136. hud/adapters/common/tests/test_adapter.py +0 -289
  137. hud/adapters/common/types.py +0 -446
  138. hud/adapters/operator/__init__.py +0 -5
  139. hud/adapters/operator/adapter.py +0 -108
  140. hud/adapters/operator/tests/__init__.py +0 -1
  141. hud/adapters/operator/tests/test_adapter.py +0 -370
  142. hud/agent/__init__.py +0 -19
  143. hud/agent/base.py +0 -126
  144. hud/agent/claude.py +0 -271
  145. hud/agent/langchain.py +0 -215
  146. hud/agent/misc/__init__.py +0 -3
  147. hud/agent/operator.py +0 -268
  148. hud/agent/tests/__init__.py +0 -1
  149. hud/agent/tests/test_base.py +0 -202
  150. hud/env/__init__.py +0 -11
  151. hud/env/client.py +0 -35
  152. hud/env/docker_client.py +0 -349
  153. hud/env/environment.py +0 -446
  154. hud/env/local_docker_client.py +0 -358
  155. hud/env/remote_client.py +0 -212
  156. hud/env/remote_docker_client.py +0 -292
  157. hud/gym.py +0 -130
  158. hud/job.py +0 -773
  159. hud/mcp/__init__.py +0 -17
  160. hud/mcp/base.py +0 -631
  161. hud/mcp/client.py +0 -312
  162. hud/mcp/tests/test_base.py +0 -512
  163. hud/mcp/tests/test_claude.py +0 -294
  164. hud/task.py +0 -149
  165. hud/taskset.py +0 -237
  166. hud/telemetry/_trace.py +0 -347
  167. hud/telemetry/context.py +0 -230
  168. hud/telemetry/exporter.py +0 -575
  169. hud/telemetry/instrumentation/__init__.py +0 -3
  170. hud/telemetry/instrumentation/mcp.py +0 -259
  171. hud/telemetry/instrumentation/registry.py +0 -59
  172. hud/telemetry/mcp_models.py +0 -270
  173. hud/telemetry/tests/__init__.py +0 -1
  174. hud/telemetry/tests/test_context.py +0 -210
  175. hud/telemetry/tests/test_trace.py +0 -312
  176. hud/tools/helper/README.md +0 -56
  177. hud/tools/helper/__init__.py +0 -9
  178. hud/tools/helper/mcp_server.py +0 -78
  179. hud/tools/helper/server_initialization.py +0 -115
  180. hud/tools/helper/utils.py +0 -58
  181. hud/trajectory.py +0 -94
  182. hud/utils/agent.py +0 -37
  183. hud/utils/common.py +0 -256
  184. hud/utils/config.py +0 -120
  185. hud/utils/deprecation.py +0 -115
  186. hud/utils/misc.py +0 -53
  187. hud/utils/tests/test_common.py +0 -277
  188. hud/utils/tests/test_config.py +0 -129
  189. hud_python-0.3.5.dist-info/METADATA +0 -284
  190. hud_python-0.3.5.dist-info/RECORD +0 -120
  191. /hud/{adapters/common → shared}/tests/__init__.py +0 -0
  192. {hud_python-0.3.5.dist-info → hud_python-0.4.0.dist-info}/WHEEL +0 -0
@@ -1,446 +0,0 @@
1
- from __future__ import annotations
2
-
3
- from typing import Annotated, Any, Literal, TypeAlias
4
-
5
- from pydantic import BaseModel, Field
6
-
7
- LogType = str | dict[str, Any] | list[str | dict[str, Any]] | None
8
-
9
-
10
- # Helper function to format logs for display
11
- def _format_logs_for_display(
12
- logs: LogType | None = None,
13
- reasoning: str | None = None,
14
- max_log_len: int = 277,
15
- ) -> str:
16
- log_repr = repr(logs)
17
- truncated_log = log_repr[:max_log_len] + "..." if len(log_repr) > max_log_len else log_repr
18
- return f" │ Reasoning: {reasoning} │ Logs: {truncated_log}"
19
-
20
-
21
- # Base class for all actions
22
- class CLAAction(BaseModel):
23
- type: str
24
- reasoning: str | None = None
25
- logs: LogType | None = None
26
-
27
- def __str__(self) -> str:
28
- # Basic representation for actions that don't have a specific override
29
- # This base __str__ will NOT include logs by default, subclasses should handle it.
30
- attributes = ", ".join(
31
- f"{k}='{v}'" if isinstance(v, str) else f"{k}={v}"
32
- for k, v in self.model_dump().items()
33
- if k != "type" and v is not None and k != "logs" and k != "reasoning"
34
- )
35
- action_str = f"{self.type.capitalize()}Action ({attributes})"
36
- action_str += _format_logs_for_display(self.logs, self.reasoning)
37
- return action_str
38
-
39
-
40
- # Basic Point model for coordinates
41
- class Point(BaseModel):
42
- x: int
43
- y: int
44
-
45
-
46
- # CLICK ACTION
47
- class ClickAction(CLAAction):
48
- type: Literal["click"] = "click"
49
- point: Point | None = None
50
- button: CLAButton = "left"
51
- pattern: list[int] | None = None
52
- hold_keys: list[CLAKey] | None = None
53
-
54
- def __str__(self) -> str:
55
- parts = ["💥 Click"]
56
- if self.point:
57
- parts.append(f"at ({self.point.x}, {self.point.y})")
58
- if self.button != "left":
59
- parts.append(f"with {self.button} button")
60
- if self.hold_keys:
61
- parts.append(f"holding {self.hold_keys}")
62
- action_str = " ".join(parts)
63
- action_str += _format_logs_for_display(self.logs, self.reasoning)
64
- return action_str
65
-
66
-
67
- # PRESS ACTION for key presses/hotkeys
68
- class PressAction(CLAAction):
69
- type: Literal["press"] = "press"
70
- keys: list[CLAKey]
71
-
72
- def __str__(self) -> str:
73
- action_str = f"🎹 Press keys: {'+'.join(self.keys)}"
74
- action_str += _format_logs_for_display(self.logs, self.reasoning)
75
- return action_str
76
-
77
-
78
- # KEYDOWN ACTION for key presses/hotkeys
79
- class KeyDownAction(CLAAction):
80
- type: Literal["keydown"] = "keydown"
81
- keys: list[CLAKey]
82
-
83
- def __str__(self) -> str:
84
- action_str = f"👇 KeyDown: {'+'.join(self.keys)}"
85
- action_str += _format_logs_for_display(self.logs, self.reasoning)
86
- return action_str
87
-
88
-
89
- # KEYUP ACTION for key presses/hotkeys
90
- class KeyUpAction(CLAAction):
91
- type: Literal["keyup"] = "keyup"
92
- keys: list[CLAKey]
93
-
94
- def __str__(self) -> str:
95
- action_str = f"👆 KeyUp: {'+'.join(self.keys)}"
96
- action_str += _format_logs_for_display(self.logs, self.reasoning)
97
- return action_str
98
-
99
-
100
- # TYPE ACTION for text typing
101
- class TypeAction(CLAAction):
102
- type: Literal["type"] = "type"
103
- text: str
104
- enter_after: bool | None = False
105
-
106
- def __str__(self) -> str:
107
- action_str = f'✍️ Type: "{self.text}"'
108
- if self.enter_after:
109
- action_str += " (and press Enter)"
110
- action_str += _format_logs_for_display(self.logs, self.reasoning)
111
- return action_str
112
-
113
-
114
- # SCROLL ACTION
115
- class ScrollAction(CLAAction):
116
- type: Literal["scroll"] = "scroll"
117
- point: Point | None = None
118
- scroll: Point | None = None
119
- hold_keys: list[CLAKey] | None = None
120
-
121
- def __str__(self) -> str:
122
- parts = ["📄 Scroll"]
123
- if self.point:
124
- parts.append(f"at ({self.point.x}, {self.point.y})")
125
- if self.scroll:
126
- parts.append(f"by ({self.scroll.x}, {self.scroll.y})")
127
- if self.hold_keys: # Added hold_keys for scroll
128
- parts.append(f"holding {self.hold_keys}")
129
- action_str = " ".join(parts)
130
- action_str += _format_logs_for_display(self.logs, self.reasoning)
131
- return action_str
132
-
133
-
134
- # MOVE ACTION for mouse movement
135
- class MoveAction(CLAAction):
136
- type: Literal["move"] = "move"
137
- point: Point | None = None
138
- offset: Point | None = None
139
-
140
- def __str__(self) -> str:
141
- parts = ["✨ Move"]
142
- if self.point:
143
- parts.append(f"to ({self.point.x},{self.point.y})")
144
- if self.offset:
145
- parts.append(f"by ({self.offset.x},{self.offset.y})")
146
- action_str = " ".join(parts)
147
- action_str += _format_logs_for_display(self.logs, self.reasoning)
148
- return action_str
149
-
150
-
151
- # WAIT ACTION
152
- class WaitAction(CLAAction):
153
- type: Literal["wait"] = "wait"
154
- time: int
155
-
156
- def __str__(self) -> str:
157
- action_str = f"💤 Wait for {self.time}ms"
158
- action_str += _format_logs_for_display(self.logs, self.reasoning)
159
- return action_str
160
-
161
-
162
- # DRAG ACTION
163
- class DragAction(CLAAction):
164
- type: Literal["drag"] = "drag"
165
- path: list[Point]
166
- pattern: list[int] | None = None # [delay_1, delay_2, ...]
167
- hold_keys: list[CLAKey] | None = None
168
-
169
- def __str__(self) -> str:
170
- parts = ["🤏 Drag"]
171
- if self.path and len(self.path) > 0:
172
- if len(self.path) == 1:
173
- parts.append(f"at ({self.path[0].x},{self.path[0].y})")
174
- else:
175
- parts.append(
176
- f"from ({self.path[0].x}, {self.path[0].y}) to "
177
- f"({self.path[-1].x}, {self.path[-1].y})"
178
- )
179
- if self.hold_keys: # Added hold_keys for drag
180
- parts.append(f"holding {self.hold_keys}")
181
- action_str = " ".join(parts)
182
- action_str += _format_logs_for_display(self.logs, self.reasoning)
183
- return action_str
184
-
185
-
186
- # RESPONSE ACTION from agent
187
- class ResponseAction(CLAAction):
188
- type: Literal["response"] = "response"
189
- text: str # The final textual response from the agent
190
-
191
- def __str__(self) -> str:
192
- displayed_text = self.text if len(self.text) < 50 else self.text[:47] + "..."
193
- action_str = f'💬 Response: "{displayed_text}"'
194
- action_str += _format_logs_for_display(self.logs, self.reasoning)
195
- return action_str
196
-
197
-
198
- # SCREENSHOT ACTION
199
- class ScreenshotFetch(CLAAction):
200
- type: Literal["screenshot"] = "screenshot"
201
-
202
- def __str__(self) -> str:
203
- action_str = "📸 Screenshot"
204
- action_str += _format_logs_for_display(self.logs, self.reasoning)
205
- return action_str
206
-
207
-
208
- class PositionFetch(CLAAction):
209
- type: Literal["position"] = "position"
210
-
211
- def __str__(self) -> str:
212
- action_str = "📍 Position"
213
- action_str += _format_logs_for_display(self.logs, self.reasoning)
214
- return action_str
215
-
216
-
217
- class CustomAction(CLAAction):
218
- type: Literal["custom"] = "custom"
219
- action: str
220
- args: dict[str, Any] | None = None
221
-
222
- def __str__(self) -> str:
223
- action_str = f"⚙️ Custom: {self.action} {self.args}"
224
- action_str += _format_logs_for_display(self.logs, self.reasoning)
225
- return action_str
226
-
227
-
228
- # Union of all possible actions
229
- CLA = Annotated[
230
- ClickAction
231
- | PressAction
232
- | KeyDownAction
233
- | KeyUpAction
234
- | TypeAction
235
- | ResponseAction
236
- | ScrollAction
237
- | MoveAction
238
- | WaitAction
239
- | DragAction
240
- | CustomAction
241
- | ScreenshotFetch
242
- | PositionFetch,
243
- Field(discriminator="type"),
244
- ]
245
-
246
-
247
- CLAKey: TypeAlias = Literal[
248
- # Control keys
249
- "backspace",
250
- "tab",
251
- "enter",
252
- "shift",
253
- "shiftleft",
254
- "shiftright",
255
- "ctrl",
256
- "ctrlleft",
257
- "ctrlright",
258
- "alt",
259
- "altleft",
260
- "altright",
261
- "pause",
262
- "capslock",
263
- "esc",
264
- "escape",
265
- "space",
266
- "pageup",
267
- "pagedown",
268
- "end",
269
- "home",
270
- "left",
271
- "up",
272
- "right",
273
- "down",
274
- "select",
275
- "print",
276
- "execute",
277
- "printscreen",
278
- "prtsc",
279
- "insert",
280
- "delete",
281
- "help",
282
- "sleep",
283
- # Special keys
284
- "numlock",
285
- "scrolllock",
286
- "clear",
287
- "separator",
288
- "modechange",
289
- "apps",
290
- "browserback",
291
- "browserfavorites",
292
- "browserforward",
293
- "browserhome",
294
- "browserrefresh",
295
- "browsersearch",
296
- "browserstop",
297
- "launchapp1",
298
- "launchapp2",
299
- "launchmail",
300
- "launchmediaselect",
301
- "playpause",
302
- "start",
303
- "stop",
304
- "prevtrack",
305
- "nexttrack",
306
- "volumemute",
307
- "volumeup",
308
- "volumedown",
309
- "zoom",
310
- # Modifier keys
311
- "win",
312
- "winleft",
313
- "winright",
314
- "command",
315
- "option",
316
- "optionleft",
317
- "optionright",
318
- "fn",
319
- # Numpad keys
320
- "num0",
321
- "num1",
322
- "num2",
323
- "num3",
324
- "num4",
325
- "num5",
326
- "num6",
327
- "num7",
328
- "num8",
329
- "num9",
330
- "multiply",
331
- "add",
332
- "subtract",
333
- "decimal",
334
- "divide",
335
- # Function keys
336
- "f1",
337
- "f2",
338
- "f3",
339
- "f4",
340
- "f5",
341
- "f6",
342
- "f7",
343
- "f8",
344
- "f9",
345
- "f10",
346
- "f11",
347
- "f12",
348
- "f13",
349
- "f14",
350
- "f15",
351
- "f16",
352
- "f17",
353
- "f18",
354
- "f19",
355
- "f20",
356
- "f21",
357
- "f22",
358
- "f23",
359
- "f24",
360
- # Language-specific keys
361
- "hanguel",
362
- "hangul",
363
- "hanja",
364
- "kana",
365
- "kanji",
366
- "junja",
367
- "convert",
368
- "nonconvert",
369
- "yen",
370
- # Characters
371
- "\t",
372
- "\n",
373
- "\r",
374
- " ",
375
- "!",
376
- '"',
377
- "#",
378
- "$",
379
- "%",
380
- "&",
381
- "'",
382
- "(",
383
- ")",
384
- "*",
385
- "+",
386
- ",",
387
- "-",
388
- ".",
389
- "/",
390
- "0",
391
- "1",
392
- "2",
393
- "3",
394
- "4",
395
- "5",
396
- "6",
397
- "7",
398
- "8",
399
- "9",
400
- ":",
401
- ";",
402
- "<",
403
- "=",
404
- ">",
405
- "?",
406
- "@",
407
- "[",
408
- "\\",
409
- "]",
410
- "^",
411
- "_",
412
- "`",
413
- "a",
414
- "b",
415
- "c",
416
- "d",
417
- "e",
418
- "f",
419
- "g",
420
- "h",
421
- "i",
422
- "j",
423
- "k",
424
- "l",
425
- "m",
426
- "n",
427
- "o",
428
- "p",
429
- "q",
430
- "r",
431
- "s",
432
- "t",
433
- "u",
434
- "v",
435
- "w",
436
- "x",
437
- "y",
438
- "z",
439
- "{",
440
- "|",
441
- "}",
442
- "~",
443
- ]
444
-
445
-
446
- CLAButton: TypeAlias = Literal["left", "right", "middle", "back", "forward"]
@@ -1,5 +0,0 @@
1
- from __future__ import annotations
2
-
3
- from .adapter import OperatorAdapter
4
-
5
- __all__ = ["OperatorAdapter"]
@@ -1,108 +0,0 @@
1
- from __future__ import annotations
2
-
3
- from typing import Any, ClassVar
4
-
5
- from hud.adapters.common import CLA, Adapter
6
- from hud.adapters.common.types import (
7
- CLAButton,
8
- CLAKey,
9
- ClickAction,
10
- CustomAction,
11
- DragAction,
12
- MoveAction,
13
- Point,
14
- PressAction,
15
- ResponseAction,
16
- ScreenshotFetch,
17
- ScrollAction,
18
- TypeAction,
19
- WaitAction,
20
- )
21
-
22
-
23
- class OperatorAdapter(Adapter):
24
- KEY_MAP: ClassVar[dict[str, CLAKey]] = {
25
- "return": "enter",
26
- "arrowup": "up",
27
- "arrowdown": "down",
28
- "arrowleft": "left",
29
- "arrowright": "right",
30
- "cmd": "ctrl",
31
- "super": "win",
32
- }
33
-
34
- BUTTON_MAP: ClassVar[dict[str, CLAButton]] = {"wheel": "middle"}
35
-
36
- def __init__(self) -> None:
37
- super().__init__()
38
- # OpenAI Computer Use default dimensions
39
- self.agent_width = 1024
40
- self.agent_height = 768
41
-
42
- def _map_key(self, key: str) -> CLAKey:
43
- """Map a key to its standardized form."""
44
- return self.KEY_MAP.get(key.lower(), key.lower()) # type: ignore
45
-
46
- def convert(self, data: Any) -> CLA:
47
- """Convert a Computer Use action to a HUD action"""
48
- try:
49
- action_type = data.get("type")
50
-
51
- if action_type == "click":
52
- x, y = data.get("x", 0), data.get("y", 0)
53
- button = data.get("button", "left")
54
- button = self.BUTTON_MAP.get(button, button)
55
- if button is None:
56
- button = "left"
57
- converted_action = ClickAction(point=Point(x=x, y=y), button=button)
58
-
59
- elif action_type == "double_click":
60
- x, y = data.get("x", 0), data.get("y", 0)
61
- converted_action = ClickAction(point=Point(x=x, y=y), button="left", pattern=[100])
62
-
63
- elif action_type == "scroll":
64
- x, y = int(data.get("x", 0)), int(data.get("y", 0))
65
- scroll_x = int(data.get("scroll_x", 0))
66
- scroll_y = int(data.get("scroll_y", 0))
67
- converted_action = ScrollAction(
68
- point=Point(x=x, y=y), scroll=Point(x=scroll_x, y=scroll_y)
69
- )
70
-
71
- elif action_type == "type":
72
- text = data.get("text", "")
73
- converted_action = TypeAction(text=text, enter_after=False)
74
-
75
- elif action_type == "wait":
76
- ms = data.get("ms", 1000)
77
- converted_action = WaitAction(time=ms)
78
-
79
- elif action_type == "move":
80
- x, y = data.get("x", 0), data.get("y", 0)
81
- converted_action = MoveAction(point=Point(x=x, y=y))
82
-
83
- elif action_type == "keypress":
84
- keys = data.get("keys", [])
85
- converted_action = PressAction(keys=[self._map_key(k) for k in keys])
86
-
87
- elif action_type == "drag":
88
- path = data.get("path", [])
89
- points = [Point(x=p.get("x", 0), y=p.get("y", 0)) for p in path]
90
- converted_action = DragAction(path=points)
91
-
92
- elif action_type == "screenshot":
93
- converted_action = ScreenshotFetch()
94
-
95
- elif action_type == "response":
96
- converted_action = ResponseAction(text=data.get("text", ""))
97
- elif action_type == "custom":
98
- converted_action = CustomAction(action=data.get("action", ""))
99
- else:
100
- raise ValueError(f"Unsupported action type: {action_type}")
101
-
102
- converted_action.reasoning = data.get("reasoning", "")
103
- converted_action.logs = data.get("logs", "")
104
-
105
- return converted_action
106
-
107
- except Exception as e:
108
- raise ValueError(f"Invalid action: {data}. Error: {e!s}") from e
@@ -1 +0,0 @@
1
- # Tests for hud.adapters.operator module