Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
11 changes: 10 additions & 1 deletion .github/workflows/release.yml
Original file line number Diff line number Diff line change
Expand Up @@ -14,9 +14,18 @@ jobs:
- name: Install uv
uses: astral-sh/setup-uv@v5

- name: Build and publish to PyPi
- name: Build and publish 'hud' to PyPI
env:
UV_PUBLISH_TOKEN: ${{ secrets.PYPI_API_TOKEN }}
run: |
uv build
uv publish

# 'hud-python' is an empty shim that depends on 'hud' (the package was
# renamed). Published in lockstep so old install commands keep working.
- name: Build and publish 'hud-python' shim to PyPI
env:
UV_PUBLISH_TOKEN: ${{ secrets.PYPI_API_TOKEN }}
run: |
uv build shim
uv publish shim/dist/*
2 changes: 1 addition & 1 deletion CONTRIBUTING.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ We welcome contributions to the HUD SDK! This guide covers how to get started.
## Quick Start

1. Fork the repository
2. Clone your fork: `git clone https://github.com/YOUR-USERNAME/hud-python`
2. Clone your fork: `git clone https://github.com/YOUR-USERNAME/hud-python` (the repo keeps its historical name; the PyPI package is `hud`)
3. Install [uv](https://docs.astral.sh/uv/) and set up dev dependencies:
```bash
cd hud-python
Expand Down
8 changes: 5 additions & 3 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ HUD is a platform for building RL environments for AI agents, across coding, bro

To learn more, see the [documentation](https://docs.hud.ai) and [environment reference](https://docs.hud.ai/v6/reference/environment).

[![PyPI](https://img.shields.io/pypi/v/hud-python?style=flat-square)](https://pypi.org/project/hud-python/)
[![PyPI](https://img.shields.io/pypi/v/hud?style=flat-square)](https://pypi.org/project/hud/)
[![License](https://img.shields.io/badge/license-MIT-green?style=flat-square)](LICENSE)
[![Add docs to Cursor](https://img.shields.io/badge/Add%20docs%20to-Cursor-black?style=flat-square)](https://cursor.com/en/install-mcp?name=docs-hud-python&config=eyJ1cmwiOiJodHRwczovL2RvY3MuaHVkLmFpL21jcCJ9)
[![Discord](https://img.shields.io/discord/1327447144772407390?label=Discord&logo=discord&style=flat-square)](https://discord.gg/wkjtmHYYjm)
Expand All @@ -22,12 +22,14 @@ To learn more, see the [documentation](https://docs.hud.ai) and [environment ref

```bash
# Install the CLI (recommended)
uv tool install hud-python --python 3.12
uv tool install hud --python 3.12

# …or as a library
pip install hud-python
pip install hud
```

> Previously published as [`hud-python`](https://pypi.org/project/hud-python/), which now just installs `hud`. The import and CLI names are unchanged.

Get your API key at [hud.ai/project/api-keys](https://hud.ai/project/api-keys) and set it:

```bash
Expand Down
6 changes: 3 additions & 3 deletions cookbooks/a2a-chat/pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ version = "0.1.0"
description = "Serve a HUD chat task over the A2A protocol (cookbook)"
requires-python = ">=3.11,<3.13"
dependencies = [
"hud-python",
"hud",
# The scripts are written against the 0.3.x server API.
"a2a-sdk==0.3.26",
]
Expand All @@ -13,6 +13,6 @@ dependencies = [
package = false

# Track the SDK from this repo. If you copied this folder out, delete this
# block to use the released hud-python from PyPI.
# block to use the released hud from PyPI.
[tool.uv.sources]
hud-python = { path = "../..", editable = true }
hud = { path = "../..", editable = true }
6 changes: 3 additions & 3 deletions cookbooks/codex-coding/pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -4,14 +4,14 @@ version = "0.1.0"
description = "Build your own Codex with the HUD SDK (cookbook)"
requires-python = ">=3.11,<3.13"
dependencies = [
"hud-python",
"hud",
"python-dotenv",
]

[tool.uv]
package = false

# Track the SDK from this repo. If you copied this folder out, delete this
# block to use the released hud-python from PyPI.
# block to use the released hud from PyPI.
[tool.uv.sources]
hud-python = { path = "../..", editable = true }
hud = { path = "../..", editable = true }
4 changes: 2 additions & 2 deletions cookbooks/fireworks-rl-training/pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ description = "Direct Fireworks Training API RL loop over HUD-style arithmetic t
requires-python = ">=3.11,<3.13"
dependencies = [
"fireworks-ai[training]",
"hud-python",
"hud",
"matplotlib",
"python-dotenv",
"torch>=2",
Expand All @@ -16,4 +16,4 @@ dependencies = [
package = false

[tool.uv.sources]
hud-python = { path = "../..", editable = true }
hud = { path = "../..", editable = true }
2 changes: 1 addition & 1 deletion cookbooks/rl-training/ppo_custom_loss.py
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@
uv run ppo_custom_loss.py --steps 10 # set MODEL below (pick one with `hud models`)
Requires torch (declared in this cookbook's pyproject; in the SDK it is the
``hud-python[train]`` extra).
``hud[train]`` extra).
"""

from __future__ import annotations
Expand Down
6 changes: 3 additions & 3 deletions cookbooks/rl-training/pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ version = "0.1.0"
description = "On-policy RL training with the HUD SDK (cookbook)"
requires-python = ">=3.11,<3.13"
dependencies = [
"hud-python",
"hud",
"python-dotenv",
# ppo_custom_loss.py computes its loss client-side with torch autograd.
# simple_train.py (built-in loss) does not need it.
Expand All @@ -15,6 +15,6 @@ dependencies = [
package = false

# Track the SDK from this repo. If you copied this folder out, delete this
# block to use the released hud-python from PyPI.
# block to use the released hud from PyPI.
[tool.uv.sources]
hud-python = { path = "../..", editable = true }
hud = { path = "../..", editable = true }
2 changes: 1 addition & 1 deletion docs/skill.md
Original file line number Diff line number Diff line change
Expand Up @@ -220,7 +220,7 @@ Get the opponent's tokens from the gateway call with `extra_body={"return_token_
await trainer.set_head(checkpoint_id) # or: hud models head <slug> --set <id>
```

**Custom loss / primitives.** Author the loss yourself (e.g. double-sided IS) with `forward_backward_custom` — the service returns per-token tensors, your torch function makes the gradients (needs `pip install 'hud-python[train]'`). Drop to `forward_backward` + `optim_step` directly when you want the `forward_backward` metrics or gradient accumulation (`num_substeps`) in between; `step` is just the two chained.
**Custom loss / primitives.** Author the loss yourself (e.g. double-sided IS) with `forward_backward_custom` — the service returns per-token tensors, your torch function makes the gradients (needs `pip install 'hud[train]'`). Drop to `forward_backward` + `optim_step` directly when you want the `forward_backward` metrics or gradient accumulation (`num_substeps`) in between; `step` is just the two chained.

---

Expand Down
4 changes: 2 additions & 2 deletions docs/v6/advanced/robots.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -23,10 +23,10 @@ Everything below ships behind the `robot` extra (pulls in numpy + openpi-client)

<CodeGroup>
```bash uv
uv add 'hud-python[robot]'
uv add 'hud[robot]'
```
```bash pip
pip install 'hud-python[robot]'
pip install 'hud[robot]'
```
</CodeGroup>

Expand Down
2 changes: 1 addition & 1 deletion docs/v6/more/contributing.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ We welcome contributions to the HUD SDK!
3. **Install in development mode**:
```bash
uv pip install -e ".[dev]"
uv tool install --force --from "." hud-python --refresh
uv tool install --force --from "." hud --refresh
```

## Development Workflows
Expand Down
4 changes: 2 additions & 2 deletions docs/v6/more/faq.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -40,10 +40,10 @@ No - not to build environments, write tasks, or run evals. Inference happens thr
</Accordion>

<Accordion title="My environment imports a package hud can't find - why?">
A globally installed CLI (`uv tool install hud-python`) runs in its **own** Python environment, so it can't see packages from your project's venv (e.g. `playwright` in your env's dependencies). Inside a project with its own deps, add `hud-python` to the project and run it from the venv:
A globally installed CLI (`uv tool install hud`) runs in its **own** Python environment, so it can't see packages from your project's venv (e.g. `playwright` in your env's dependencies). Inside a project with its own deps, add `hud` to the project and run it from the venv:

```bash
uv add hud-python
uv add hud
uv run hud eval tasks.py claude
```
</Accordion>
Expand Down
2 changes: 1 addition & 1 deletion docs/v6/reference/cli.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ description: "Reference for the hud command-line interface: init, dev, run, eval
icon: "terminal"
---

Install the CLI with `uv tool install hud-python --python 3.12`. Authenticate once with `hud set HUD_API_KEY=...`.
Install the CLI with `uv tool install hud --python 3.12`. Authenticate once with `hud set HUD_API_KEY=...`.

## Build & iterate

Expand Down
2 changes: 1 addition & 1 deletion docs/v6/reference/training.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -148,7 +148,7 @@ the defaults (`None`) unless a provider documents a key.

`forward_backward_custom` runs the current-policy forward pass server-side, hands you per-token tensors,
runs your loss locally (torch autograd), and ships the per-token gradients back. Requires torch
(`pip install 'hud-python[train]'`).
(`pip install 'hud[train]'`).

```python
import torch
Expand Down
4 changes: 2 additions & 2 deletions docs/v6/start/quickstart.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -16,10 +16,10 @@ The rest of this page walks the setup path by hand.

<CodeGroup>
```bash uv
uv tool install hud-python --python 3.12
uv tool install hud --python 3.12
```
```bash pip
pip install hud-python
pip install hud
```
</CodeGroup>

Expand Down
37 changes: 36 additions & 1 deletion hud/__init__.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
"""hud-python.
"""hud.

tools for building, evaluating, and training AI agents.
"""
Expand Down Expand Up @@ -64,3 +64,38 @@
from .version import __version__
except ImportError:
__version__ = "unknown"


def _warn_legacy_hud_python() -> None:
"""Warn when a pre-rename hud-python install sits alongside this package.

The SDK was published as ``hud-python`` before the rename to ``hud``.
``hud-python`` releases older than the rename ship their own copy of the
``hud`` package, so installing both makes the installer silently overwrite
one with the other. Post-rename ``hud-python`` releases are empty shims
that just depend on ``hud`` and are fine to have installed.
"""
from importlib.metadata import PackageNotFoundError
from importlib.metadata import version as _dist_version

try:
legacy = _dist_version("hud-python")
_dist_version("hud")
except PackageNotFoundError:
return

from packaging.version import Version

if Version(legacy) < Version("0.6.9"):
import warnings

warnings.warn(
f"Both 'hud' and a pre-rename 'hud-python' ({legacy}) are installed; they ship "
"the same 'hud' package and overwrite each other. Run 'pip uninstall hud-python' "
"and then reinstall 'hud'.",
RuntimeWarning,
stacklevel=3,
)


_warn_legacy_hud_python()
2 changes: 1 addition & 1 deletion hud/agents/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -135,7 +135,7 @@ def __getattr__(name: str) -> object:
value = getattr(import_module(module_name), symbol)
except ModuleNotFoundError as exc:
raise ImportError(
f"{name} requires the agents extra. Install with: pip install 'hud-python[agents]'"
f"{name} requires the agents extra. Install with: pip install 'hud[agents]'"
) from exc
globals()[name] = value
return value
2 changes: 1 addition & 1 deletion hud/agents/browser_use/__init__.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
"""browser-use SDK integration (optional dependency ``hud-python[browseruse]``)."""
"""browser-use SDK integration (optional dependency ``hud[browseruse]``)."""

from .agent import BrowserUseAgent, BrowserUseConfig

Expand Down
2 changes: 1 addition & 1 deletion hud/agents/browser_use/agent.py
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@
The agent is stateless w.r.t. the env: it holds only config and is driven by
``await agent(run)``, receiving the run handle per call. ``browser-use`` is an
optional dependency
(``hud-python[browseruse]``), imported lazily inside ``rollout``.
(``hud[browseruse]``), imported lazily inside ``rollout``.
"""

from __future__ import annotations
Expand Down
2 changes: 1 addition & 1 deletion hud/agents/robot/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@
:class:`~hud.agents.types.ObservationStep`, and each re-inference an
:class:`~hud.agents.types.InferenceStep`, so runs stream live into the HUD trace viewer.
This subpackage needs the ``robot`` extra (``pip install 'hud-python[robot]'``) for
This subpackage needs the ``robot`` extra (``pip install 'hud[robot]'``) for
``numpy`` + ``msgpack``; importing :mod:`hud.agents` alone never pulls them in.
"""

Expand Down
2 changes: 1 addition & 1 deletion hud/agents/robot/video.py
Original file line number Diff line number Diff line change
Expand Up @@ -195,7 +195,7 @@ def __init__(self, *, fps: int, trace_id: str | None) -> None:
importlib.import_module("av")
except Exception as exc:
raise RuntimeError(
"robot video streaming requires PyAV — `pip install 'hud-python[robot]'`"
"robot video streaming requires PyAV — `pip install 'hud[robot]'`"
) from exc
self._fps = fps
self._trace_id = trace_id
Expand Down
4 changes: 2 additions & 2 deletions hud/agents/tests/test_base.py
Original file line number Diff line number Diff line change
Expand Up @@ -67,10 +67,10 @@ def find_spec(self, fullname: str, path: Any = None, target: Any = None) -> None
if "ClaudeAgent" in vars(hud.agents): # drop any cached lazy export
monkeypatch.delitem(hud.agents.__dict__, "ClaudeAgent")

with pytest.raises(ImportError, match=r"hud-python\[agents\]"):
with pytest.raises(ImportError, match=r"hud\[agents\]"):
_ = hud.agents.ClaudeAgent

with pytest.raises(ImportError, match=r"hud-python\[agents\]"):
with pytest.raises(ImportError, match=r"hud\[agents\]"):
_ = AgentType.CLAUDE.cls


Expand Down
2 changes: 1 addition & 1 deletion hud/cli/templates.py
Original file line number Diff line number Diff line change
Expand Up @@ -134,7 +134,7 @@ async def test():
name = "{name}"
version = "0.1.0"
requires-python = ">=3.11"
dependencies = ["hud-python"]
dependencies = ["hud"]

[tool.uv]
package = false
Expand Down
16 changes: 8 additions & 8 deletions hud/cli/utils/version_check.py
Original file line number Diff line number Diff line change
@@ -1,10 +1,10 @@
"""Version checking utilities for HUD CLI.

This module handles checking for updates to the hud-python package
This module handles checking for updates to the hud package
and prompting users to upgrade when a new version is available.

Features:
- Checks PyPI for the latest version of hud-python
- Checks PyPI for the latest version of hud
- Caches results for 6 hours to avoid excessive API calls
- Displays a friendly prompt when an update is available
- Can be disabled with HUD_SKIP_VERSION_CHECK=1 environment variable
Expand Down Expand Up @@ -41,7 +41,7 @@
CACHE_DURATION = 6 * 60 * 60

# PyPI API URL for package info
PYPI_URL = "https://pypi.org/pypi/hud-python/json"
PYPI_URL = "https://pypi.org/pypi/hud/json"


class VersionInfo(NamedTuple):
Expand All @@ -62,7 +62,7 @@ def _is_in_virtualenv() -> bool:


def _get_current_version() -> str:
"""Get the currently installed version of hud-python."""
"""Get the currently installed version of hud."""
try:
from hud import __version__

Expand Down Expand Up @@ -166,7 +166,7 @@ def _compare_versions(current: str, latest: str) -> bool:


def check_for_updates() -> VersionInfo | None:
"""Check for updates to hud-python.
"""Check for updates to hud.

This function checks PyPI for the latest version and caches the result
for 6 hours to avoid excessive API calls.
Expand Down Expand Up @@ -238,12 +238,12 @@ def display_update_prompt(console: HUDConsole | None = None) -> None:
info = check_for_updates()
if info and info.is_outdated:
if _is_in_virtualenv():
upgrade_cmd = "uv sync --upgrade-package hud-python"
upgrade_cmd = "uv sync --upgrade-package hud"
else:
upgrade_cmd = "uv tool upgrade hud-python"
upgrade_cmd = "uv tool upgrade hud"

console.print(
f"[yellow]🆕 A new version of hud-python is available: "
f"[yellow]🆕 A new version of hud is available: "
f"[bold cyan]{escape(info.latest)}[/bold cyan] "
f"(current: [dim]{escape(info.current)}[/dim])\n"
f" Run: [bold yellow]{escape(upgrade_cmd)}[/bold yellow] to update[/yellow]"
Expand Down
2 changes: 1 addition & 1 deletion hud/tests/test_version.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,4 +5,4 @@ def test_import():
"""Test that the package can be imported."""
import hud

assert hud.__version__ == "0.6.8"
assert hud.__version__ == "0.6.9"
4 changes: 2 additions & 2 deletions hud/train/client.py
Original file line number Diff line number Diff line change
Expand Up @@ -188,13 +188,13 @@ async def forward_backward_custom(
``forward`` → run ``loss_fn`` locally (torch autograd) → ship per-token
gradients to ``backward``. Any differentiable loss over π_θ and the
:class:`DatumTensors` scalars works (e.g. GLM double-sided IS). Requires
torch (``pip install 'hud-python[train]'``).
torch (``pip install 'hud[train]'``).
"""
try:
import torch
except ImportError as exc:
raise ImportError(
"forward_backward_custom requires torch; install 'hud-python[train]'"
"forward_backward_custom requires torch; install 'hud[train]'"
) from exc

forward = await self.forward(trajectories, group_size=group_size, reward_scale=reward_scale)
Expand Down
Loading
Loading