mirror of
https://github.com/hanzoai/agent.git
synced 2026-09-11 21:08:51 +00:00
* fix: declare what `import agents` needs, at floors 3.9 can install hanzo-agent 0.1.0 on PyPI cannot be imported from a clean install. On 3.9, agents/memory/store.py imports numpy at module level, and the wheel's METADATA does not declare it. On 3.10+, pip resolves openai 3.13.0, which replaced its httpx dependency with httpx2. agents imports httpx directly, in tracing/processors.py and models/openai_provider.py, and until now only got it through openai. main declares numpy>=2.1.0, but numpy 2.1.0 dropped 3.9, whose newest numpy is 2.0.2. requires-python still admits 3.9, so the pin cannot resolve there, and `uv lock --check` fails. - numpy: >=1.26 below 3.10, and >=2.1.0 from 3.10, which keeps the cp313t floor - httpx: >=0.23.0,<1, the range openai 2.x required - store.py imports numpy inside search_by_embedding, as retriever.py already does, so `import agents` does not need it - uv.lock: relocked. No pinned version moves; the lock was already stale for the aiohttp and cryptography floors. tests/test_packaging.py checks the declared numpy range on 3.9-3.13, that `import agents` works with numpy blocked, and the in-memory embedding search. A new CI job builds the wheel, installs it into a clean venv on 3.9 and 3.12, and imports agents and numpy. Co-Authored-By: Claude Opus 5 <[email protected]> * fix: two more places 3.9 cannot evaluate a PEP 604 union tests/test_zap.py annotates ZapAgentConfig.__init__ with `list | None` and has no `from __future__ import annotations`, so it fails collection on 3.9. That was the one error left in `pytest tests` there. agents/extensions/web3/mpc_client.py declares a pydantic field as `str | None`. Its future import does not help, because pydantic evaluates the annotation when it builds the model, and on 3.9 it can only do that with eval_type_backport installed. So `import agents.extensions.web3` fails on 3.9 even with [web3] installed. Declare the backport in the web3 extra, below 3.10, instead of rewriting the field as Optional[str]. The repo's ruff UP rules would flag Optional there, and their autofix would put the union back. On 3.9, `pytest tests` now gives 369 passed, and the web3 extension's own tests give 20 passed; before, they could not even be collected. 0.2.0, the declared floor, passes them too. Co-Authored-By: Claude Opus 5 <[email protected]> * fix: raise the web3 extra's floor to 6.20.2 On a clean 3.9 install of hanzo-agent[web3], the resolver picked web3 6.11.0 with eth-typing 5.2.1 and eth-account 0.13.7. web3 releases before 6.20.2 declare no upper bound on eth-typing, and web3 6 cannot import with eth-typing 5 ("cannot import name 'ContractName'"). 6.11 also imports pkg_resources, which a bare venv does not have. 6.20.2 is the first 6.x that caps eth-typing below 5, and 6.17.1 was the first to cap eth-account below 0.13. uv.lock already pins web3 6.20.4, so no pinned version moves. A clean [web3] install now resolves web3 6.20.4, eth-typing 4.4.0 and eth-account 0.11.3 on both 3.9 and 3.12, with no setuptools, and the extension's tests pass on both (20 each). Co-Authored-By: Claude Opus 5 <[email protected]> --------- Co-authored-by: Claude Opus 5 <[email protected]>
68 lines
2.7 KiB
Python
68 lines
2.7 KiB
Python
"""Packaging checks for hanzo-agent.
|
|
|
|
0.1.0 reached PyPI without numpy in its METADATA while ``agents/memory/store.py``
|
|
imported numpy at module level, so ``import agents`` raised ``ModuleNotFoundError``
|
|
in a clean environment. The pin that replaced it, ``numpy>=2.1.0``, cannot install
|
|
on 3.9, which requires-python still admits: numpy 2.1.0 dropped 3.9.
|
|
"""
|
|
|
|
from __future__ import annotations
|
|
|
|
import subprocess
|
|
import sys
|
|
from importlib.metadata import requires
|
|
|
|
import pytest
|
|
from packaging.requirements import Requirement
|
|
from packaging.specifiers import SpecifierSet
|
|
|
|
from agents.memory import InMemoryMemoryStore, MemoryType
|
|
|
|
# numpy 2.1.0 dropped Python 3.9 and 2.3.0 dropped 3.10, so these are the newest
|
|
# releases those interpreters can install, and they will not move.
|
|
LAST_NUMPY = {"3.9": "2.0.2", "3.10": "2.2.6"}
|
|
|
|
|
|
def _numpy_specifiers(python: str) -> list[SpecifierSet]:
|
|
env = {"python_version": python, "python_full_version": f"{python}.0", "extra": ""}
|
|
reqs = [Requirement(r) for r in requires("hanzo-agent") or []]
|
|
return [
|
|
r.specifier
|
|
for r in reqs
|
|
if r.name == "numpy" and (r.marker is None or r.marker.evaluate(env))
|
|
]
|
|
|
|
|
|
@pytest.mark.parametrize("python", ["3.9", "3.10", "3.11", "3.12", "3.13"])
|
|
def test_numpy_is_declared_on_every_supported_python(python: str) -> None:
|
|
assert _numpy_specifiers(python), f"no numpy requirement applies on Python {python}"
|
|
|
|
|
|
@pytest.mark.parametrize(("python", "version"), sorted(LAST_NUMPY.items()))
|
|
def test_numpy_floor_admits_the_last_numpy_for_old_pythons(python: str, version: str) -> None:
|
|
for spec in _numpy_specifiers(python):
|
|
assert spec.contains(version), (
|
|
f"numpy{spec} excludes {version}, the newest numpy for Python {python}"
|
|
)
|
|
|
|
|
|
def test_import_agents_does_not_need_numpy() -> None:
|
|
# A None entry in sys.modules makes `import numpy` raise ImportError.
|
|
code = "import sys; sys.modules['numpy'] = None; import agents"
|
|
result = subprocess.run([sys.executable, "-c", code], capture_output=True, text=True)
|
|
assert result.returncode == 0, result.stderr
|
|
|
|
|
|
async def test_search_by_embedding_ranks_by_cosine_similarity() -> None:
|
|
store = InMemoryMemoryStore()
|
|
same = await store.add("same", MemoryType.FACT, embedding=[1.0, 0.0])
|
|
near = await store.add("near", MemoryType.FACT, embedding=[1.0, 1.0])
|
|
await store.add("orthogonal", MemoryType.FACT, embedding=[0.0, 1.0])
|
|
await store.add("no embedding", MemoryType.FACT)
|
|
|
|
results = await store.search_by_embedding([2.0, 0.0], threshold=0.5)
|
|
|
|
assert [memory.id for memory, _ in results] == [same.id, near.id]
|
|
assert results[0][1] == pytest.approx(1.0)
|
|
assert results[1][1] == pytest.approx(2**-0.5)
|