Import AITURK IDE 1.0.0-beta.1 from Hermes 63279301; preserve MIT license

This commit is contained in:
2026-09-05 13:26:46 +03:00
commit 03634b1ca3
11340 changed files with 3442369 additions and 0 deletions
@@ -0,0 +1,166 @@
"""Runtime install progress: the slow legs must tick, never hang silently.
The incident: 'Installing runtime…' sat frozen for minutes on a slow
line — ensure_runtime_installed downloaded and extracted with no
progress stream, so both the quickstart hero and the pane's install row
showed a dead bar. Contract: _download and _extract tick per chunk /
per member, ensure_runtime_installed forwards a staged stream, and the
router's hook translates it into live job fields."""
from __future__ import annotations
import io
import zipfile
from pathlib import Path
import hermes_cli.local_runtime.binaries as binaries
from hermes_cli.web_routers.local_models import _job, _runtime_progress_hook
def _make_zip(path: Path, names_sizes: dict[str, int]) -> None:
with zipfile.ZipFile(path, "w") as z:
for name, size in names_sizes.items():
z.writestr(name, b"x" * size)
def test_extract_ticks_per_member(tmp_path):
archive = tmp_path / "runtime.zip"
_make_zip(archive, {"a.bin": 1000, "b.bin": 3000, "c.bin": 500})
ticks: list[tuple[int, int]] = []
binaries._extract(archive, tmp_path / "out",
progress=lambda d, t: ticks.append((d, t)))
assert len(ticks) == 3
total = 4500
assert all(t == total for _, t in ticks)
assert [d for d, _ in ticks] == sorted(d for d, _ in ticks)
assert ticks[-1][0] == total
assert (tmp_path / "out" / "b.bin").stat().st_size == 3000
def test_download_ticks_with_content_length(tmp_path, monkeypatch):
payload = b"y" * (3 << 20) # 3 MiB -> several 1 MiB chunks
class _Resp(io.BytesIO):
headers = {"Content-Length": str(len(payload))}
def __enter__(self):
return self
def __exit__(self, *a):
return False
monkeypatch.setattr(binaries.urllib.request, "urlopen",
lambda url, timeout=0: _Resp(payload))
ticks: list[tuple[int, int]] = []
dest = tmp_path / "asset.zip"
binaries._download("http://x/asset.zip", dest,
progress=lambda d, t: ticks.append((d, t)))
assert dest.read_bytes() == payload
assert len(ticks) >= 3
assert ticks[-1] == (len(payload), len(payload))
def test_ensure_runtime_installed_forwards_staged_progress(tmp_path, monkeypatch):
"""The full install path emits download -> verify -> extract stages
(per asset) and a final verify, all through one callback."""
monkeypatch.setattr(binaries, "runtimes_root", lambda: tmp_path)
class _Plan:
assets = ["a.zip", "b.zip"]
backend = "cuda"
install_dir = tmp_path / "b1" / "cuda"
monkeypatch.setattr(binaries, "resolve_assets", lambda tag, backend: _Plan())
monkeypatch.setattr(binaries, "verify_install", lambda d, t: "ok")
def _fake_download(url, dest, progress=None):
_make_zip(dest, {"f.bin": 2048})
if progress is not None:
progress(1024, 2048)
progress(2048, 2048)
monkeypatch.setattr(binaries, "_download", _fake_download)
events: list[tuple[str, str]] = []
binaries.ensure_runtime_installed(
"b1", "cuda",
progress=lambda stage, d, t, label: events.append((stage, label)))
stages = [s for s, _ in events]
assert "download" in stages and "extract" in stages and "verify" in stages
# Two assets -> per-asset labels on the slow stages.
assert ("download", "1/2") in events and ("download", "2/2") in events
assert ("extract", "1/2") in events and ("extract", "2/2") in events
# Stage order per asset: download before extract.
assert stages.index("download") < stages.index("extract")
def test_progress_hook_translates_stages_to_job_fields():
job = _job("quickstart", "Test Model")
hook = _runtime_progress_hook(job)
hook("download", 5 << 20, 100 << 20, "1/2")
assert job["phase"] == "downloading-runtime"
assert "1/2" in job["detail"]
assert job["done_bytes"] == 5 << 20
assert job["total_bytes"] == 100 << 20
# Rapid second tick inside the throttle window is dropped...
hook("download", 6 << 20, 100 << 20, "1/2")
assert job["done_bytes"] == 5 << 20
# ...but a terminal tick (done == total) always lands.
hook("download", 100 << 20, 100 << 20, "1/2")
assert job["done_bytes"] == 100 << 20
hook("extract", 10, 100, "")
assert job["phase"] in ("downloading-runtime", "unpacking-runtime")
job2 = _job("runtime-install", "x")
hook2 = _runtime_progress_hook(job2)
hook2("extract", 100, 100, "")
assert job2["phase"] == "unpacking-runtime"
hook2("verify", 0, 0, "")
assert job2["phase"] == "verifying-runtime"
assert job2["total_bytes"] is None # indeterminate bar, not a stuck 0%
def test_progress_hook_accumulates_across_assets(monkeypatch):
"""A two-asset engine reads as ONE growing download: the second asset's
bytes stack on the first's instead of restarting the bar at zero, and
unpack/verify leave the finished download's counters standing."""
# Drive the throttle's clock so every tick lands (the real hook drops
# sub-250ms non-terminal ticks; this test is about arithmetic, not
# pacing — pacing has its own assertions above).
from hermes_cli.web_routers import local_models as lm
clock = {"now": 0.0}
def fake_monotonic():
clock["now"] += 1.0
return clock["now"]
monkeypatch.setattr(lm.time, "monotonic", fake_monotonic)
job = _job("runtime-install", "engine")
hook = _runtime_progress_hook(job)
hook("download", 40 << 20, 40 << 20, "1/2")
assert job["done_bytes"] == 40 << 20
assert job["total_bytes"] == 40 << 20
# Second asset starts: counters continue from the first asset's total.
hook("download", 0, 60 << 20, "2/2")
assert job["done_bytes"] == 40 << 20
assert job["total_bytes"] == 100 << 20
hook("download", 60 << 20, 60 << 20, "2/2")
assert job["done_bytes"] == 100 << 20
assert job["total_bytes"] == 100 << 20
# Unpack and verify narrate without rewinding the finished bar.
hook("extract", 1, 100, "2/2")
assert job["phase"] == "unpacking-runtime"
assert job["done_bytes"] == 100 << 20
hook("verify", 0, 0, "")
assert job["phase"] == "verifying-runtime"
assert job["done_bytes"] == 100 << 20