Add ReinOpenWeights adapter, closing GLAS-WP-0001-T05
glas_harness/reins/rein_openweights.py implements the Rein ABC by shelling out to `rein-openweights run --task-file ... --no-hub [--model ...]`, mirroring reins/rein_aharness.py exactly. Factored the duplicated git_head/write_task_file logic into reins/_shared.py, used by both adapters now. registry/reins/rein-openweights.yaml flipped to status: implemented. 8 new tests (mocked subprocess), 18/18 passing. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
This commit is contained in:
parent
4bdf8de950
commit
266f99a2fe
8 changed files with 238 additions and 43 deletions
|
|
@ -80,8 +80,10 @@ def test_end_session_detects_new_commit(tmp_path) -> None:
|
|||
subprocess.run(["git", "init", "-q"], cwd=repo, check=True)
|
||||
subprocess.run(["git", "commit", "-q", "--allow-empty", "-m", "init"], cwd=repo, check=True)
|
||||
|
||||
from glas_harness.reins._shared import git_head
|
||||
|
||||
rein = ReinAharness()
|
||||
head_before = rein._git_head(str(repo))
|
||||
head_before = git_head(str(repo))
|
||||
|
||||
subprocess.run(["git", "commit", "-q", "--allow-empty", "-m", "task"], cwd=repo, check=True)
|
||||
|
||||
|
|
@ -96,8 +98,10 @@ def test_end_session_no_new_commit(tmp_path) -> None:
|
|||
subprocess.run(["git", "init", "-q"], cwd=repo, check=True)
|
||||
subprocess.run(["git", "commit", "-q", "--allow-empty", "-m", "init"], cwd=repo, check=True)
|
||||
|
||||
from glas_harness.reins._shared import git_head
|
||||
|
||||
rein = ReinAharness()
|
||||
head = rein._git_head(str(repo))
|
||||
head = git_head(str(repo))
|
||||
|
||||
summary = rein.end_session({"target_repo": str(repo), "head_before": head})
|
||||
assert summary["committed"] == "False"
|
||||
|
|
|
|||
106
tests/test_rein_openweights.py
Normal file
106
tests/test_rein_openweights.py
Normal file
|
|
@ -0,0 +1,106 @@
|
|||
import json
|
||||
import subprocess
|
||||
from unittest.mock import MagicMock, patch
|
||||
|
||||
import pytest
|
||||
|
||||
from glas_harness.contract import Rein, SandboxHandle, ToolCall
|
||||
from glas_harness.reins.rein_openweights import ReinOpenWeights, ReinOpenWeightsNotInstalled
|
||||
|
||||
|
||||
def test_is_rein_subclass() -> None:
|
||||
assert issubclass(ReinOpenWeights, Rein)
|
||||
|
||||
|
||||
def test_bin_raises_if_not_installed() -> None:
|
||||
rein = ReinOpenWeights(cli_bin="does-not-exist-binary")
|
||||
with pytest.raises(ReinOpenWeightsNotInstalled):
|
||||
rein._bin()
|
||||
|
||||
|
||||
def test_start_session_writes_task_file_and_captures_head(tmp_path) -> None:
|
||||
repo = tmp_path / "repo"
|
||||
repo.mkdir()
|
||||
subprocess.run(["git", "init", "-q"], cwd=repo, check=True)
|
||||
subprocess.run(["git", "commit", "-q", "--allow-empty", "-m", "init"], cwd=repo, check=True)
|
||||
|
||||
rein = ReinOpenWeights()
|
||||
sandbox = SandboxHandle(sandbox_id="abc", host="localhost", reachability={"workspace_dir": str(repo)})
|
||||
session = rein.start_session(
|
||||
profile={"id": "harness.agent-dev-local"},
|
||||
inputs={"title": "t", "description": "d"},
|
||||
sandbox=sandbox,
|
||||
)
|
||||
|
||||
assert session["target_repo"] == str(repo)
|
||||
assert session["head_before"]
|
||||
task_spec = json.loads(open(session["task_file"]).read())
|
||||
assert task_spec["title"] == "t"
|
||||
assert task_spec["target_repo"] == str(repo)
|
||||
|
||||
|
||||
def test_start_session_requires_resolvable_target_repo() -> None:
|
||||
rein = ReinOpenWeights()
|
||||
sandbox = SandboxHandle(sandbox_id="abc", host="localhost", reachability={})
|
||||
with pytest.raises(ValueError, match="target_repo"):
|
||||
rein.start_session(profile={}, inputs={"title": "t", "description": "d"}, sandbox=sandbox)
|
||||
|
||||
|
||||
def test_dispatch_tool_invokes_rein_openweights_cli() -> None:
|
||||
rein = ReinOpenWeights()
|
||||
session = {"task_file": "/tmp/task.json"}
|
||||
|
||||
fake_result = MagicMock(returncode=0, stdout="ok", stderr="")
|
||||
with patch.object(rein, "_bin", return_value="/usr/bin/rein-openweights"):
|
||||
with patch("glas_harness.reins.rein_openweights.subprocess.run", return_value=fake_result) as run:
|
||||
result = rein.dispatch_tool(session, ToolCall(name="run_task"))
|
||||
|
||||
argv = run.call_args.args[0]
|
||||
assert argv[:3] == ["/usr/bin/rein-openweights", "run", "--task-file"]
|
||||
assert "--no-hub" in argv
|
||||
assert result.ok is True
|
||||
assert result.output == "ok"
|
||||
|
||||
|
||||
def test_dispatch_tool_passes_model_when_set() -> None:
|
||||
rein = ReinOpenWeights(model="meta-llama/llama-3.1-70b-instruct")
|
||||
session = {"task_file": "/tmp/task.json"}
|
||||
fake_result = MagicMock(returncode=0, stdout="ok", stderr="")
|
||||
|
||||
with patch.object(rein, "_bin", return_value="/usr/bin/rein-openweights"):
|
||||
with patch("glas_harness.reins.rein_openweights.subprocess.run", return_value=fake_result) as run:
|
||||
rein.dispatch_tool(session, ToolCall(name="run_task"))
|
||||
|
||||
argv = run.call_args.args[0]
|
||||
assert "--model" in argv
|
||||
assert "meta-llama/llama-3.1-70b-instruct" in argv
|
||||
|
||||
|
||||
def test_dispatch_tool_reports_failure() -> None:
|
||||
rein = ReinOpenWeights()
|
||||
session = {"task_file": "/tmp/task.json"}
|
||||
|
||||
fake_result = MagicMock(returncode=1, stdout="", stderr="boom")
|
||||
with patch.object(rein, "_bin", return_value="/usr/bin/rein-openweights"):
|
||||
with patch("glas_harness.reins.rein_openweights.subprocess.run", return_value=fake_result):
|
||||
result = rein.dispatch_tool(session, ToolCall(name="run_task"))
|
||||
|
||||
assert result.ok is False
|
||||
assert result.error == "boom"
|
||||
|
||||
|
||||
def test_end_session_detects_new_commit(tmp_path) -> None:
|
||||
repo = tmp_path / "repo"
|
||||
repo.mkdir()
|
||||
subprocess.run(["git", "init", "-q"], cwd=repo, check=True)
|
||||
subprocess.run(["git", "commit", "-q", "--allow-empty", "-m", "init"], cwd=repo, check=True)
|
||||
|
||||
rein = ReinOpenWeights()
|
||||
from glas_harness.reins._shared import git_head
|
||||
|
||||
head_before = git_head(str(repo))
|
||||
subprocess.run(["git", "commit", "-q", "--allow-empty", "-m", "task"], cwd=repo, check=True)
|
||||
|
||||
summary = rein.end_session({"target_repo": str(repo), "head_before": head_before})
|
||||
assert summary["committed"] == "True"
|
||||
assert summary["commit_sha"] != head_before
|
||||
Loading…
Add table
Add a link
Reference in a new issue