hud-python 0.4.15__py3-none-any.whl → 0.4.17__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/cli/rl/utils.py ADDED
@@ -0,0 +1,165 @@
1
+ """Shared utilities for RL commands."""
2
+
3
+ from __future__ import annotations
4
+
5
+ import logging
6
+ from pathlib import Path
7
+ from typing import Any
8
+
9
+ import yaml
10
+
11
+ from hud.utils.design import HUDDesign
12
+
13
+ design = HUDDesign()
14
+
15
+ logger = logging.getLogger(__name__)
16
+
17
+
18
+ def read_lock_file() -> dict[str, Any]:
19
+ """Read and parse hud.lock.yaml file."""
20
+ lock_file = Path("hud.lock.yaml")
21
+ if not lock_file.exists():
22
+ return {}
23
+
24
+ try:
25
+ with open(lock_file) as f:
26
+ return yaml.safe_load(f) or {}
27
+ except Exception as e:
28
+ design.warning(f"Could not read hud.lock.yaml: {e}")
29
+ return {}
30
+
31
+
32
+ def write_lock_file(data: dict[str, Any]) -> bool:
33
+ """Write data to hud.lock.yaml file."""
34
+ lock_file = Path("hud.lock.yaml")
35
+
36
+ try:
37
+ with open(lock_file, "w") as f:
38
+ yaml.dump(data, f, default_flow_style=False, sort_keys=False)
39
+ return True
40
+ except Exception as e:
41
+ design.warning(f"Could not write hud.lock.yaml: {e}")
42
+ return False
43
+
44
+
45
+ def get_mcp_config_from_lock() -> dict[str, Any] | None:
46
+ """Get MCP configuration from lock file."""
47
+ lock_data = read_lock_file()
48
+
49
+ # Check if there's an image reference
50
+ image = lock_data.get("image")
51
+ if image:
52
+ return {
53
+ "hud": {
54
+ "url": "https://mcp.hud.so/v3/mcp",
55
+ "headers": {"Authorization": "Bearer $HUD_API_KEY", "Mcp-Image": image},
56
+ }
57
+ }
58
+
59
+ return None
60
+
61
+
62
+ def get_primary_dataset() -> str | None:
63
+ """Get primary dataset name from lock file."""
64
+ lock_data = read_lock_file()
65
+ return lock_data.get("primary_dataset", {}).get("name")
66
+
67
+
68
+ def get_image_from_lock() -> str | None:
69
+ """Get image name from lock file."""
70
+ lock_data = read_lock_file()
71
+ return lock_data.get("image")
72
+
73
+
74
+ def detect_image_name() -> str | None:
75
+ """Try to detect image name from various sources."""
76
+ # First check lock file
77
+ image = get_image_from_lock()
78
+ if image:
79
+ return image
80
+
81
+ # Check pyproject.toml
82
+ pyproject = Path("pyproject.toml")
83
+ if pyproject.exists():
84
+ try:
85
+ import tomllib
86
+
87
+ with open(pyproject, "rb") as f:
88
+ data = tomllib.load(f)
89
+
90
+ # Check for hud.image_name
91
+ image = data.get("tool", {}).get("hud", {}).get("image_name")
92
+ if image:
93
+ return image
94
+
95
+ # Use project name
96
+ name = data.get("project", {}).get("name")
97
+ if name:
98
+ return f"{name}:latest"
99
+ except Exception:
100
+ logger.warning("Failed to load pyproject.toml")
101
+
102
+ # Use directory name as last resort
103
+ return f"{Path.cwd().name}:latest"
104
+
105
+
106
+ def validate_dataset_name(name: str) -> bool:
107
+ """Validate HuggingFace dataset name format."""
108
+ if not name:
109
+ return False
110
+
111
+ if "/" not in name:
112
+ design.error(f"Invalid dataset name: {name}")
113
+ design.info("Dataset name should be in format: org/dataset")
114
+ return False
115
+
116
+ parts = name.split("/")
117
+ if len(parts) != 2:
118
+ design.error(f"Invalid dataset name: {name}")
119
+ return False
120
+
121
+ org, dataset = parts
122
+ if not org or not dataset:
123
+ design.error(f"Invalid dataset name: {name}")
124
+ return False
125
+
126
+ # Check for valid characters (alphanumeric, dash, underscore)
127
+ import re
128
+
129
+ if not re.match(r"^[a-zA-Z0-9_-]+$", org) or not re.match(r"^[a-zA-Z0-9_-]+$", dataset):
130
+ design.error(f"Invalid characters in dataset name: {name}")
131
+ design.info("Use only letters, numbers, dashes, and underscores")
132
+ return False
133
+
134
+ return True
135
+
136
+
137
+ def create_tasks_template() -> list[dict[str, Any]]:
138
+ """Create a template for tasks.json file."""
139
+ return [
140
+ {
141
+ "id": "example-task-001",
142
+ "prompt": "Complete the first TODO item in the list",
143
+ "mcp_config": {
144
+ "# TODO": "Add your MCP configuration here",
145
+ "# Example for remote": {
146
+ "hud": {
147
+ "url": "https://mcp.hud.so/v3/mcp",
148
+ "headers": {
149
+ "Authorization": "Bearer $HUD_API_KEY",
150
+ "Mcp-Image": "your-org/your-env:latest",
151
+ },
152
+ }
153
+ },
154
+ "# Example for local": {
155
+ "local": {"command": "docker", "args": ["run", "--rm", "-i", "your-env:latest"]}
156
+ },
157
+ },
158
+ "setup_tool": {"name": "setup", "arguments": {"name": "todo_seed", "num_items": 5}},
159
+ "evaluate_tool": {
160
+ "name": "evaluate",
161
+ "arguments": {"name": "todo_completed", "expected_count": 1},
162
+ },
163
+ "metadata": {"difficulty": "easy", "category": "task_completion"},
164
+ }
165
+ ]
@@ -5,4 +5,4 @@ def test_import():
5
5
  """Test that the package can be imported."""
6
6
  import hud
7
7
 
8
- assert hud.__version__ == "0.4.15"
8
+ assert hud.__version__ == "0.4.17"
hud/version.py CHANGED
@@ -4,4 +4,4 @@ Version information for the HUD SDK.
4
4
 
5
5
  from __future__ import annotations
6
6
 
7
- __version__ = "0.4.15"
7
+ __version__ = "0.4.17"
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: hud-python
3
- Version: 0.4.15
3
+ Version: 0.4.17
4
4
  Summary: SDK for the HUD platform.
5
5
  Project-URL: Homepage, https://github.com/hud-evals/hud-python
6
6
  Project-URL: Bug Tracker, https://github.com/hud-evals/hud-python/issues
@@ -2,12 +2,12 @@ hud/__init__.py,sha256=BjAhZtsHbGN371Q8t3o4v4jltedkmDE85xW0yOILU9g,397
2
2
  hud/__main__.py,sha256=YR8Dq8OhINOsVfQ55PmRXXg4fEK84Rt_-rMtJ5rvhWo,145
3
3
  hud/settings.py,sha256=q9aZiHjvbL4oLE-N8AttTW4rmzS8zPMnsca-iMGyEGc,2362
4
4
  hud/types.py,sha256=gNnyS1G7aYHIR5sT3k3bOfSTFnPylUO6lNGLWbjbeYk,5149
5
- hud/version.py,sha256=gdxZtcCpnCv32fA8VZnQ530MgJHh6ZS7pyG585pb6No,105
5
+ hud/version.py,sha256=EkdQIoYM_NJvpzVexCJEPP60FkfL3uxxcA80nz-GVIE,105
6
6
  hud/agents/__init__.py,sha256=UoIkljWdbq4bM0LD-mSaw6w826EqdEjOk7r6glNYwYQ,286
7
7
  hud/agents/base.py,sha256=rbwYP_a6XTwhY_5CaBlE7SWflnTq1EOuDiNY2XeUWdM,28275
8
- hud/agents/claude.py,sha256=in-dRByL7wU1gsuwFvscltQ1PGZURb2bIeU3QFhfpQU,14271
8
+ hud/agents/claude.py,sha256=_eD_XKZhVJ6grkHQfbS6JskztueomQcmJeGJMbfNdmE,14534
9
9
  hud/agents/langchain.py,sha256=1EgCy8jfjunsWxlPC5XfvfLS6_XZVrIF1ZjtHcrvhYw,9584
10
- hud/agents/openai.py,sha256=9G7u17oN9yne7ObiuaBV67a3U3byC-NPJchDT4s5kZ0,13994
10
+ hud/agents/openai.py,sha256=tvFYsZ5yaoLkfjMnHe-COxRttMsLRXBLPdSqgeipQRk,14257
11
11
  hud/agents/openai_chat_generic.py,sha256=jTJ-KY6HkglPK0iwZH5v3PVnaUjDsWc9IbRo3AbXlyE,5322
12
12
  hud/agents/misc/__init__.py,sha256=BYi4Ytp9b_vycpZFXnr5Oyw6ncKLNNGml8Jrb7bWUb4,136
13
13
  hud/agents/misc/response_agent.py,sha256=MsnIVElXM4ABrSJfEc_MMYp1Y_Rxmkq4kEGJ9vDX7hw,3098
@@ -30,6 +30,13 @@ hud/cli/list_func.py,sha256=ENxLL4X5uuqAASWZdQuI0k-tEzmlhUn5LATgz3QPQqQ,7065
30
30
  hud/cli/pull.py,sha256=JHwCwUwRO0Nzbgm9mkjsz6EpxbxgwQVhgNSY64nNZ-s,11969
31
31
  hud/cli/push.py,sha256=4KrEHj0_i3xJNCB3eRjANmHFhSW4MFfpnld3nfVYENs,17904
32
32
  hud/cli/remove.py,sha256=USAvB6pbMA3jd19xUtLEBiMsklVTEfE2Maw9nYcpSAE,6619
33
+ hud/cli/rl/README.md,sha256=3pqRZMrnwD-lJwWGCCNZNhGdZG6zyydLBOer0e8BkLw,5983
34
+ hud/cli/rl/__init__.py,sha256=g_Crqn5o0m9xANrTOkQZENWVlwHAV6MWiobte-FfqiY,3412
35
+ hud/cli/rl/init.py,sha256=GXVOXLrX8CVAgpJ1pHuk6Y6oujbh46Rtz8kG18jGzk8,13789
36
+ hud/cli/rl/pod.py,sha256=ZiXI-RG9YsnKx1EWzufcqklBdaD_d6XFtD45a0H8KpM,18837
37
+ hud/cli/rl/ssh.py,sha256=bHAieonseJPON7P1mwB2GPWKLDlLZuvQniONmr5ZfcE,11523
38
+ hud/cli/rl/train.py,sha256=sjY4J0TCp8647kzuIHyEeIsFVGtE0tllT0GzhkPPrWY,19895
39
+ hud/cli/rl/utils.py,sha256=ZW3sjl5KaHZaOCjAbut_QIpQvxgzlxjPGuM6fuYkU9I,4836
33
40
  hud/cli/tests/__init__.py,sha256=ZrGVkmH7DHXGqOvjOSNGZeMYaFIRB2K8c6hwr8FPJ-8,68
34
41
  hud/cli/tests/test_analyze.py,sha256=SwxvRlnw-VaEwKN2nd1FJAxfhieujPjh7PdQh_LYJ5E,11050
35
42
  hud/cli/tests/test_analyze_metadata.py,sha256=s-N-ETJECloiNQhdnZrfvxDI4pWBI8hl8edQNSRaw14,9982
@@ -150,10 +157,10 @@ hud/utils/tests/test_init.py,sha256=2QLQSGgyP9wJhOvPCusm_zjJad0qApOZi1BXpxcdHXQ,
150
157
  hud/utils/tests/test_mcp.py,sha256=0pUa16mL-bqbZDXp5NHBnt1gO5o10BOg7zTMHZ1DNPM,4023
151
158
  hud/utils/tests/test_progress.py,sha256=QSF7Kpi03Ff_l3mAeqW9qs1nhK50j9vBiSobZq7T4f4,7394
152
159
  hud/utils/tests/test_telemetry.py,sha256=5jl7bEx8C8b-FfFUko5pf4UY-mPOR-9HaeL98dGtVHM,2781
153
- hud/utils/tests/test_version.py,sha256=2-9cqVBlHbL7SFxZhLBPPAg3ZuiZKQvwFqiXE0lUcyY,160
160
+ hud/utils/tests/test_version.py,sha256=-u0egMJ2Q8IPrenCiVP8k2f_n7BSBRB2tYFGdbUwWrM,160
154
161
  hud/py.typed,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
155
- hud_python-0.4.15.dist-info/METADATA,sha256=B1t1zBp1c5qjI9HkygWl_K2RBix1A27iIqR7moxoLsc,20287
156
- hud_python-0.4.15.dist-info/WHEEL,sha256=qtCwoSJWgHk21S1Kb4ihdzI2rlJ1ZKaIurTj_ngOhyQ,87
157
- hud_python-0.4.15.dist-info/entry_points.txt,sha256=jJbodNFg1m0-CDofe5AHvB4zKBq7sSdP97-ohaQ3ae4,63
158
- hud_python-0.4.15.dist-info/licenses/LICENSE,sha256=yIzBheVUf86FC1bztAcr7RYWWNxyd3B-UJQ3uddg1HA,1078
159
- hud_python-0.4.15.dist-info/RECORD,,
162
+ hud_python-0.4.17.dist-info/METADATA,sha256=z3k06ixt6r41EDxaHYtbwILpjU1Z5QVxiQ6Jwfu-BWs,20287
163
+ hud_python-0.4.17.dist-info/WHEEL,sha256=qtCwoSJWgHk21S1Kb4ihdzI2rlJ1ZKaIurTj_ngOhyQ,87
164
+ hud_python-0.4.17.dist-info/entry_points.txt,sha256=jJbodNFg1m0-CDofe5AHvB4zKBq7sSdP97-ohaQ3ae4,63
165
+ hud_python-0.4.17.dist-info/licenses/LICENSE,sha256=yIzBheVUf86FC1bztAcr7RYWWNxyd3B-UJQ3uddg1HA,1078
166
+ hud_python-0.4.17.dist-info/RECORD,,