hud-python 0.4.1__py3-none-any.whl → 0.4.3__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.
- hud/__init__.py +22 -22
- hud/agents/__init__.py +13 -15
- hud/agents/base.py +599 -599
- hud/agents/claude.py +373 -373
- hud/agents/langchain.py +261 -250
- hud/agents/misc/__init__.py +7 -7
- hud/agents/misc/response_agent.py +82 -80
- hud/agents/openai.py +352 -352
- hud/agents/openai_chat_generic.py +154 -154
- hud/agents/tests/__init__.py +1 -1
- hud/agents/tests/test_base.py +742 -742
- hud/agents/tests/test_claude.py +324 -324
- hud/agents/tests/test_client.py +363 -363
- hud/agents/tests/test_openai.py +237 -237
- hud/cli/__init__.py +617 -617
- hud/cli/__main__.py +8 -8
- hud/cli/analyze.py +371 -371
- hud/cli/analyze_metadata.py +230 -230
- hud/cli/build.py +498 -427
- hud/cli/clone.py +185 -185
- hud/cli/cursor.py +92 -92
- hud/cli/debug.py +392 -392
- hud/cli/docker_utils.py +83 -83
- hud/cli/init.py +280 -281
- hud/cli/interactive.py +353 -353
- hud/cli/mcp_server.py +764 -756
- hud/cli/pull.py +330 -336
- hud/cli/push.py +404 -370
- hud/cli/remote_runner.py +311 -311
- hud/cli/runner.py +160 -160
- hud/cli/tests/__init__.py +3 -3
- hud/cli/tests/test_analyze.py +284 -284
- hud/cli/tests/test_cli_init.py +265 -265
- hud/cli/tests/test_cli_main.py +27 -27
- hud/cli/tests/test_clone.py +142 -142
- hud/cli/tests/test_cursor.py +253 -253
- hud/cli/tests/test_debug.py +453 -453
- hud/cli/tests/test_mcp_server.py +139 -139
- hud/cli/tests/test_utils.py +388 -388
- hud/cli/utils.py +263 -263
- hud/clients/README.md +143 -143
- hud/clients/__init__.py +16 -16
- hud/clients/base.py +378 -379
- hud/clients/fastmcp.py +222 -222
- hud/clients/mcp_use.py +298 -278
- hud/clients/tests/__init__.py +1 -1
- hud/clients/tests/test_client_integration.py +111 -111
- hud/clients/tests/test_fastmcp.py +342 -342
- hud/clients/tests/test_protocol.py +188 -188
- hud/clients/utils/__init__.py +1 -1
- hud/clients/utils/retry_transport.py +160 -160
- hud/datasets.py +327 -322
- hud/misc/__init__.py +1 -1
- hud/misc/claude_plays_pokemon.py +292 -292
- hud/otel/__init__.py +35 -35
- hud/otel/collector.py +142 -142
- hud/otel/config.py +164 -164
- hud/otel/context.py +536 -536
- hud/otel/exporters.py +366 -366
- hud/otel/instrumentation.py +97 -97
- hud/otel/processors.py +118 -118
- hud/otel/tests/__init__.py +1 -1
- hud/otel/tests/test_processors.py +197 -197
- hud/server/__init__.py +5 -5
- hud/server/context.py +114 -114
- hud/server/helper/__init__.py +5 -5
- hud/server/low_level.py +132 -132
- hud/server/server.py +170 -166
- hud/server/tests/__init__.py +3 -3
- hud/settings.py +73 -73
- hud/shared/__init__.py +5 -5
- hud/shared/exceptions.py +180 -180
- hud/shared/requests.py +264 -264
- hud/shared/tests/test_exceptions.py +157 -157
- hud/shared/tests/test_requests.py +275 -275
- hud/telemetry/__init__.py +25 -25
- hud/telemetry/instrument.py +379 -379
- hud/telemetry/job.py +309 -309
- hud/telemetry/replay.py +74 -74
- hud/telemetry/trace.py +83 -83
- hud/tools/__init__.py +33 -33
- hud/tools/base.py +365 -365
- hud/tools/bash.py +161 -161
- hud/tools/computer/__init__.py +15 -15
- hud/tools/computer/anthropic.py +437 -437
- hud/tools/computer/hud.py +376 -376
- hud/tools/computer/openai.py +295 -295
- hud/tools/computer/settings.py +82 -82
- hud/tools/edit.py +314 -314
- hud/tools/executors/__init__.py +30 -30
- hud/tools/executors/base.py +539 -539
- hud/tools/executors/pyautogui.py +621 -621
- hud/tools/executors/tests/__init__.py +1 -1
- hud/tools/executors/tests/test_base_executor.py +338 -338
- hud/tools/executors/tests/test_pyautogui_executor.py +165 -165
- hud/tools/executors/xdo.py +511 -511
- hud/tools/playwright.py +412 -412
- hud/tools/tests/__init__.py +3 -3
- hud/tools/tests/test_base.py +282 -282
- hud/tools/tests/test_bash.py +158 -158
- hud/tools/tests/test_bash_extended.py +197 -197
- hud/tools/tests/test_computer.py +425 -425
- hud/tools/tests/test_computer_actions.py +34 -34
- hud/tools/tests/test_edit.py +259 -259
- hud/tools/tests/test_init.py +27 -27
- hud/tools/tests/test_playwright_tool.py +183 -183
- hud/tools/tests/test_tools.py +145 -145
- hud/tools/tests/test_utils.py +156 -156
- hud/tools/types.py +72 -72
- hud/tools/utils.py +50 -50
- hud/types.py +136 -136
- hud/utils/__init__.py +10 -10
- hud/utils/async_utils.py +65 -65
- hud/utils/design.py +236 -168
- hud/utils/mcp.py +55 -55
- hud/utils/progress.py +149 -149
- hud/utils/telemetry.py +66 -66
- hud/utils/tests/test_async_utils.py +173 -173
- hud/utils/tests/test_init.py +17 -17
- hud/utils/tests/test_progress.py +261 -261
- hud/utils/tests/test_telemetry.py +82 -82
- hud/utils/tests/test_version.py +8 -8
- hud/version.py +7 -7
- {hud_python-0.4.1.dist-info → hud_python-0.4.3.dist-info}/METADATA +10 -8
- hud_python-0.4.3.dist-info/RECORD +131 -0
- {hud_python-0.4.1.dist-info → hud_python-0.4.3.dist-info}/licenses/LICENSE +21 -21
- hud/agents/art.py +0 -101
- hud_python-0.4.1.dist-info/RECORD +0 -132
- {hud_python-0.4.1.dist-info → hud_python-0.4.3.dist-info}/WHEEL +0 -0
- {hud_python-0.4.1.dist-info → hud_python-0.4.3.dist-info}/entry_points.txt +0 -0
hud/telemetry/replay.py
CHANGED
|
@@ -1,74 +1,74 @@
|
|
|
1
|
-
"""Trace retrieval and replay functionality.
|
|
2
|
-
|
|
3
|
-
This module provides APIs to retrieve collected traces for analysis,
|
|
4
|
-
debugging, and replay purposes.
|
|
5
|
-
"""
|
|
6
|
-
|
|
7
|
-
from __future__ import annotations
|
|
8
|
-
|
|
9
|
-
from typing import TYPE_CHECKING
|
|
10
|
-
|
|
11
|
-
from hud.otel.collector import clear_trace as _clear_trace
|
|
12
|
-
from hud.otel.collector import get_trace as _get_trace
|
|
13
|
-
|
|
14
|
-
if TYPE_CHECKING:
|
|
15
|
-
from hud.types import Trace
|
|
16
|
-
|
|
17
|
-
__all__ = ["clear_trace", "get_trace"]
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
def get_trace(task_run_id: str) -> Trace | None:
|
|
21
|
-
"""Retrieve the collected trace for a task run.
|
|
22
|
-
|
|
23
|
-
Returns None if trace collection was disabled or the trace doesn't exist.
|
|
24
|
-
|
|
25
|
-
Args:
|
|
26
|
-
task_run_id: The task run ID to retrieve the trace for
|
|
27
|
-
|
|
28
|
-
Returns:
|
|
29
|
-
Trace object containing all collected steps, or None if not found
|
|
30
|
-
|
|
31
|
-
Usage:
|
|
32
|
-
import hud
|
|
33
|
-
|
|
34
|
-
# Run agent with tracing
|
|
35
|
-
with hud.trace() as task_run_id:
|
|
36
|
-
agent = MyAgent()
|
|
37
|
-
result = await agent.run("solve task")
|
|
38
|
-
|
|
39
|
-
# Get the trace for analysis
|
|
40
|
-
trace = hud.get_trace(task_run_id)
|
|
41
|
-
if trace:
|
|
42
|
-
print(f"Collected {len(trace.trace)} steps")
|
|
43
|
-
|
|
44
|
-
# Analyze agent vs MCP steps
|
|
45
|
-
agent_steps = [s for s in trace.trace if s.category == "agent"]
|
|
46
|
-
mcp_steps = [s for s in trace.trace if s.category == "mcp"]
|
|
47
|
-
|
|
48
|
-
print(f"Agent steps: {len(agent_steps)}")
|
|
49
|
-
print(f"MCP steps: {len(mcp_steps)}")
|
|
50
|
-
|
|
51
|
-
# Replay or analyze individual steps
|
|
52
|
-
for step in trace.trace:
|
|
53
|
-
if step.category == "agent" and step.result:
|
|
54
|
-
print(f"Agent: {step.result.get('content') if isinstance(step.result, dict) else step.result}")
|
|
55
|
-
if step.category == "mcp" and step.request:
|
|
56
|
-
print(f"MCP: {step.request.method if hasattr(step.request, 'method') else step.request}")
|
|
57
|
-
""" # noqa: E501
|
|
58
|
-
return _get_trace(task_run_id)
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
def clear_trace(task_run_id: str) -> None:
|
|
62
|
-
"""Clear the collected trace for a task run ID.
|
|
63
|
-
|
|
64
|
-
Useful for cleaning up memory after processing large traces.
|
|
65
|
-
|
|
66
|
-
Args:
|
|
67
|
-
task_run_id: The task run ID to clear the trace for
|
|
68
|
-
|
|
69
|
-
Usage:
|
|
70
|
-
trace = hud.get_trace(task_run_id)
|
|
71
|
-
# Process trace...
|
|
72
|
-
hud.clear_trace(task_run_id) # Free memory
|
|
73
|
-
"""
|
|
74
|
-
_clear_trace(task_run_id)
|
|
1
|
+
"""Trace retrieval and replay functionality.
|
|
2
|
+
|
|
3
|
+
This module provides APIs to retrieve collected traces for analysis,
|
|
4
|
+
debugging, and replay purposes.
|
|
5
|
+
"""
|
|
6
|
+
|
|
7
|
+
from __future__ import annotations
|
|
8
|
+
|
|
9
|
+
from typing import TYPE_CHECKING
|
|
10
|
+
|
|
11
|
+
from hud.otel.collector import clear_trace as _clear_trace
|
|
12
|
+
from hud.otel.collector import get_trace as _get_trace
|
|
13
|
+
|
|
14
|
+
if TYPE_CHECKING:
|
|
15
|
+
from hud.types import Trace
|
|
16
|
+
|
|
17
|
+
__all__ = ["clear_trace", "get_trace"]
|
|
18
|
+
|
|
19
|
+
|
|
20
|
+
def get_trace(task_run_id: str) -> Trace | None:
|
|
21
|
+
"""Retrieve the collected trace for a task run.
|
|
22
|
+
|
|
23
|
+
Returns None if trace collection was disabled or the trace doesn't exist.
|
|
24
|
+
|
|
25
|
+
Args:
|
|
26
|
+
task_run_id: The task run ID to retrieve the trace for
|
|
27
|
+
|
|
28
|
+
Returns:
|
|
29
|
+
Trace object containing all collected steps, or None if not found
|
|
30
|
+
|
|
31
|
+
Usage:
|
|
32
|
+
import hud
|
|
33
|
+
|
|
34
|
+
# Run agent with tracing
|
|
35
|
+
with hud.trace() as task_run_id:
|
|
36
|
+
agent = MyAgent()
|
|
37
|
+
result = await agent.run("solve task")
|
|
38
|
+
|
|
39
|
+
# Get the trace for analysis
|
|
40
|
+
trace = hud.get_trace(task_run_id)
|
|
41
|
+
if trace:
|
|
42
|
+
print(f"Collected {len(trace.trace)} steps")
|
|
43
|
+
|
|
44
|
+
# Analyze agent vs MCP steps
|
|
45
|
+
agent_steps = [s for s in trace.trace if s.category == "agent"]
|
|
46
|
+
mcp_steps = [s for s in trace.trace if s.category == "mcp"]
|
|
47
|
+
|
|
48
|
+
print(f"Agent steps: {len(agent_steps)}")
|
|
49
|
+
print(f"MCP steps: {len(mcp_steps)}")
|
|
50
|
+
|
|
51
|
+
# Replay or analyze individual steps
|
|
52
|
+
for step in trace.trace:
|
|
53
|
+
if step.category == "agent" and step.result:
|
|
54
|
+
print(f"Agent: {step.result.get('content') if isinstance(step.result, dict) else step.result}")
|
|
55
|
+
if step.category == "mcp" and step.request:
|
|
56
|
+
print(f"MCP: {step.request.method if hasattr(step.request, 'method') else step.request}")
|
|
57
|
+
""" # noqa: E501
|
|
58
|
+
return _get_trace(task_run_id)
|
|
59
|
+
|
|
60
|
+
|
|
61
|
+
def clear_trace(task_run_id: str) -> None:
|
|
62
|
+
"""Clear the collected trace for a task run ID.
|
|
63
|
+
|
|
64
|
+
Useful for cleaning up memory after processing large traces.
|
|
65
|
+
|
|
66
|
+
Args:
|
|
67
|
+
task_run_id: The task run ID to clear the trace for
|
|
68
|
+
|
|
69
|
+
Usage:
|
|
70
|
+
trace = hud.get_trace(task_run_id)
|
|
71
|
+
# Process trace...
|
|
72
|
+
hud.clear_trace(task_run_id) # Free memory
|
|
73
|
+
"""
|
|
74
|
+
_clear_trace(task_run_id)
|
hud/telemetry/trace.py
CHANGED
|
@@ -1,83 +1,83 @@
|
|
|
1
|
-
"""User-facing trace context manager for HUD telemetry.
|
|
2
|
-
|
|
3
|
-
This module provides the simple trace() API that users interact with.
|
|
4
|
-
The actual OpenTelemetry implementation is in hud.otel.
|
|
5
|
-
"""
|
|
6
|
-
|
|
7
|
-
from __future__ import annotations
|
|
8
|
-
|
|
9
|
-
import uuid
|
|
10
|
-
from contextlib import contextmanager
|
|
11
|
-
from typing import TYPE_CHECKING, Any
|
|
12
|
-
|
|
13
|
-
from hud.otel import configure_telemetry
|
|
14
|
-
from hud.otel import trace as OtelTrace
|
|
15
|
-
|
|
16
|
-
if TYPE_CHECKING:
|
|
17
|
-
from collections.abc import Generator
|
|
18
|
-
|
|
19
|
-
__all__ = ["trace"]
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
@contextmanager
|
|
23
|
-
def trace(
|
|
24
|
-
name: str = "Test task from hud",
|
|
25
|
-
*,
|
|
26
|
-
root: bool = True,
|
|
27
|
-
attrs: dict[str, Any] | None = None,
|
|
28
|
-
job_id: str | None = None,
|
|
29
|
-
task_id: str | None = None,
|
|
30
|
-
) -> Generator[str, None, None]:
|
|
31
|
-
"""Start a HUD trace context.
|
|
32
|
-
|
|
33
|
-
A unique task_run_id is automatically generated for each trace.
|
|
34
|
-
|
|
35
|
-
Args:
|
|
36
|
-
name: Descriptive name for this trace/task
|
|
37
|
-
root: Whether this is a root trace (updates task status)
|
|
38
|
-
attrs: Additional attributes to attach to the trace
|
|
39
|
-
job_id: Optional job ID to associate with this trace
|
|
40
|
-
|
|
41
|
-
Yields:
|
|
42
|
-
str: The auto-generated task run ID
|
|
43
|
-
|
|
44
|
-
Usage:
|
|
45
|
-
import hud
|
|
46
|
-
|
|
47
|
-
with hud.trace("My Task") as task_run_id:
|
|
48
|
-
# Your code here
|
|
49
|
-
print(f"Running task: {task_run_id}")
|
|
50
|
-
|
|
51
|
-
# Or with default name:
|
|
52
|
-
with hud.trace() as task_run_id:
|
|
53
|
-
pass
|
|
54
|
-
|
|
55
|
-
# Or with job_id:
|
|
56
|
-
with hud.trace("My Task", job_id="550e8400-e29b-41d4-a716-446655440000") as task_run_id:
|
|
57
|
-
pass
|
|
58
|
-
"""
|
|
59
|
-
# Ensure telemetry is configured
|
|
60
|
-
configure_telemetry()
|
|
61
|
-
|
|
62
|
-
# Only generate task_run_id if using HUD backend
|
|
63
|
-
# For custom OTLP backends, we don't need it
|
|
64
|
-
from hud.settings import get_settings
|
|
65
|
-
|
|
66
|
-
settings = get_settings()
|
|
67
|
-
|
|
68
|
-
if settings.telemetry_enabled and settings.api_key:
|
|
69
|
-
task_run_id = str(uuid.uuid4())
|
|
70
|
-
else:
|
|
71
|
-
# Use a placeholder for custom backends
|
|
72
|
-
task_run_id = "custom-otlp-trace"
|
|
73
|
-
|
|
74
|
-
# Delegate to OpenTelemetry implementation
|
|
75
|
-
with OtelTrace(
|
|
76
|
-
task_run_id,
|
|
77
|
-
is_root=root,
|
|
78
|
-
span_name=name,
|
|
79
|
-
attributes=attrs or {},
|
|
80
|
-
job_id=job_id,
|
|
81
|
-
task_id=task_id,
|
|
82
|
-
) as run_id:
|
|
83
|
-
yield run_id
|
|
1
|
+
"""User-facing trace context manager for HUD telemetry.
|
|
2
|
+
|
|
3
|
+
This module provides the simple trace() API that users interact with.
|
|
4
|
+
The actual OpenTelemetry implementation is in hud.otel.
|
|
5
|
+
"""
|
|
6
|
+
|
|
7
|
+
from __future__ import annotations
|
|
8
|
+
|
|
9
|
+
import uuid
|
|
10
|
+
from contextlib import contextmanager
|
|
11
|
+
from typing import TYPE_CHECKING, Any
|
|
12
|
+
|
|
13
|
+
from hud.otel import configure_telemetry
|
|
14
|
+
from hud.otel import trace as OtelTrace
|
|
15
|
+
|
|
16
|
+
if TYPE_CHECKING:
|
|
17
|
+
from collections.abc import Generator
|
|
18
|
+
|
|
19
|
+
__all__ = ["trace"]
|
|
20
|
+
|
|
21
|
+
|
|
22
|
+
@contextmanager
|
|
23
|
+
def trace(
|
|
24
|
+
name: str = "Test task from hud",
|
|
25
|
+
*,
|
|
26
|
+
root: bool = True,
|
|
27
|
+
attrs: dict[str, Any] | None = None,
|
|
28
|
+
job_id: str | None = None,
|
|
29
|
+
task_id: str | None = None,
|
|
30
|
+
) -> Generator[str, None, None]:
|
|
31
|
+
"""Start a HUD trace context.
|
|
32
|
+
|
|
33
|
+
A unique task_run_id is automatically generated for each trace.
|
|
34
|
+
|
|
35
|
+
Args:
|
|
36
|
+
name: Descriptive name for this trace/task
|
|
37
|
+
root: Whether this is a root trace (updates task status)
|
|
38
|
+
attrs: Additional attributes to attach to the trace
|
|
39
|
+
job_id: Optional job ID to associate with this trace
|
|
40
|
+
|
|
41
|
+
Yields:
|
|
42
|
+
str: The auto-generated task run ID
|
|
43
|
+
|
|
44
|
+
Usage:
|
|
45
|
+
import hud
|
|
46
|
+
|
|
47
|
+
with hud.trace("My Task") as task_run_id:
|
|
48
|
+
# Your code here
|
|
49
|
+
print(f"Running task: {task_run_id}")
|
|
50
|
+
|
|
51
|
+
# Or with default name:
|
|
52
|
+
with hud.trace() as task_run_id:
|
|
53
|
+
pass
|
|
54
|
+
|
|
55
|
+
# Or with job_id:
|
|
56
|
+
with hud.trace("My Task", job_id="550e8400-e29b-41d4-a716-446655440000") as task_run_id:
|
|
57
|
+
pass
|
|
58
|
+
"""
|
|
59
|
+
# Ensure telemetry is configured
|
|
60
|
+
configure_telemetry()
|
|
61
|
+
|
|
62
|
+
# Only generate task_run_id if using HUD backend
|
|
63
|
+
# For custom OTLP backends, we don't need it
|
|
64
|
+
from hud.settings import get_settings
|
|
65
|
+
|
|
66
|
+
settings = get_settings()
|
|
67
|
+
|
|
68
|
+
if settings.telemetry_enabled and settings.api_key:
|
|
69
|
+
task_run_id = str(uuid.uuid4())
|
|
70
|
+
else:
|
|
71
|
+
# Use a placeholder for custom backends
|
|
72
|
+
task_run_id = "custom-otlp-trace"
|
|
73
|
+
|
|
74
|
+
# Delegate to OpenTelemetry implementation
|
|
75
|
+
with OtelTrace(
|
|
76
|
+
task_run_id,
|
|
77
|
+
is_root=root,
|
|
78
|
+
span_name=name,
|
|
79
|
+
attributes=attrs or {},
|
|
80
|
+
job_id=job_id,
|
|
81
|
+
task_id=task_id,
|
|
82
|
+
) as run_id:
|
|
83
|
+
yield run_id
|
hud/tools/__init__.py
CHANGED
|
@@ -1,33 +1,33 @@
|
|
|
1
|
-
"""HUD tools for computer control, file editing, and bash commands."""
|
|
2
|
-
|
|
3
|
-
from __future__ import annotations
|
|
4
|
-
|
|
5
|
-
from typing import TYPE_CHECKING, Any
|
|
6
|
-
|
|
7
|
-
from .base import BaseHub, BaseTool
|
|
8
|
-
from .bash import BashTool
|
|
9
|
-
from .edit import EditTool
|
|
10
|
-
from .playwright import PlaywrightTool
|
|
11
|
-
|
|
12
|
-
if TYPE_CHECKING:
|
|
13
|
-
from .computer import AnthropicComputerTool, HudComputerTool, OpenAIComputerTool
|
|
14
|
-
|
|
15
|
-
__all__ = [
|
|
16
|
-
"AnthropicComputerTool",
|
|
17
|
-
"BaseHub",
|
|
18
|
-
"BaseTool",
|
|
19
|
-
"BashTool",
|
|
20
|
-
"EditTool",
|
|
21
|
-
"HudComputerTool",
|
|
22
|
-
"OpenAIComputerTool",
|
|
23
|
-
"PlaywrightTool",
|
|
24
|
-
]
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
def __getattr__(name: str) -> Any:
|
|
28
|
-
"""Lazy import computer tools to avoid importing pyautogui unless needed."""
|
|
29
|
-
if name in ("AnthropicComputerTool", "HudComputerTool", "OpenAIComputerTool"):
|
|
30
|
-
from . import computer
|
|
31
|
-
|
|
32
|
-
return getattr(computer, name)
|
|
33
|
-
raise AttributeError(f"module '{__name__}' has no attribute '{name}'")
|
|
1
|
+
"""HUD tools for computer control, file editing, and bash commands."""
|
|
2
|
+
|
|
3
|
+
from __future__ import annotations
|
|
4
|
+
|
|
5
|
+
from typing import TYPE_CHECKING, Any
|
|
6
|
+
|
|
7
|
+
from .base import BaseHub, BaseTool
|
|
8
|
+
from .bash import BashTool
|
|
9
|
+
from .edit import EditTool
|
|
10
|
+
from .playwright import PlaywrightTool
|
|
11
|
+
|
|
12
|
+
if TYPE_CHECKING:
|
|
13
|
+
from .computer import AnthropicComputerTool, HudComputerTool, OpenAIComputerTool
|
|
14
|
+
|
|
15
|
+
__all__ = [
|
|
16
|
+
"AnthropicComputerTool",
|
|
17
|
+
"BaseHub",
|
|
18
|
+
"BaseTool",
|
|
19
|
+
"BashTool",
|
|
20
|
+
"EditTool",
|
|
21
|
+
"HudComputerTool",
|
|
22
|
+
"OpenAIComputerTool",
|
|
23
|
+
"PlaywrightTool",
|
|
24
|
+
]
|
|
25
|
+
|
|
26
|
+
|
|
27
|
+
def __getattr__(name: str) -> Any:
|
|
28
|
+
"""Lazy import computer tools to avoid importing pyautogui unless needed."""
|
|
29
|
+
if name in ("AnthropicComputerTool", "HudComputerTool", "OpenAIComputerTool"):
|
|
30
|
+
from . import computer
|
|
31
|
+
|
|
32
|
+
return getattr(computer, name)
|
|
33
|
+
raise AttributeError(f"module '{__name__}' has no attribute '{name}'")
|