104 lines
3.7 KiB
Python
104 lines
3.7 KiB
Python
import json
|
|
import subprocess
|
|
from unittest.mock import patch
|
|
|
|
from rein_openweights.loop import LoopResult
|
|
from rein_openweights.runner import run_task
|
|
|
|
|
|
def _init_repo(tmp_path):
|
|
subprocess.run(["git", "init", "-q"], cwd=tmp_path, check=True)
|
|
subprocess.run(["git", "config", "user.email", "t@example.com"], cwd=tmp_path, check=True)
|
|
subprocess.run(["git", "config", "user.name", "t"], cwd=tmp_path, check=True)
|
|
subprocess.run(["git", "commit", "-q", "--allow-empty", "-m", "init"], cwd=tmp_path, check=True)
|
|
return tmp_path
|
|
|
|
|
|
def _task_file(tmp_path, repo):
|
|
task = tmp_path / "task.json"
|
|
task.write_text(
|
|
json.dumps({"title": "t", "description": "d", "target_repo": str(repo)})
|
|
)
|
|
return str(task)
|
|
|
|
|
|
def test_run_task_ok_when_loop_produces_a_commit(tmp_path):
|
|
repo = _init_repo(tmp_path)
|
|
task_file = _task_file(tmp_path, repo)
|
|
|
|
def fake_run_loop(client, repo_root, title, description, *, max_turns, budget):
|
|
subprocess.run(["git", "-C", str(repo_root), "commit", "-q", "--allow-empty", "-m", "task"])
|
|
budget.consume(500)
|
|
return LoopResult(turns=2, finished=True)
|
|
|
|
with (
|
|
patch("rein_openweights.runner.resolve_openrouter_api_key", return_value="sk-test"),
|
|
patch("rein_openweights.runner.run_loop", side_effect=fake_run_loop),
|
|
patch("rein_openweights.runner.hub.post_progress_event", return_value=True),
|
|
patch("rein_openweights.runner.hub.post_token_event", return_value=True),
|
|
):
|
|
result = run_task(task_file)
|
|
|
|
assert result.ok is True
|
|
assert result.committed is True
|
|
assert result.tokens_spent == 500
|
|
|
|
|
|
def test_run_task_fails_when_no_commit_produced(tmp_path):
|
|
repo = _init_repo(tmp_path)
|
|
task_file = _task_file(tmp_path, repo)
|
|
|
|
with (
|
|
patch("rein_openweights.runner.resolve_openrouter_api_key", return_value="sk-test"),
|
|
patch(
|
|
"rein_openweights.runner.run_loop",
|
|
return_value=LoopResult(turns=1, finished=True),
|
|
),
|
|
patch("rein_openweights.runner.hub.post_progress_event", return_value=True),
|
|
patch("rein_openweights.runner.hub.post_token_event", return_value=True),
|
|
):
|
|
result = run_task(task_file)
|
|
|
|
assert result.ok is False
|
|
assert result.committed is False
|
|
assert result.reason == "no commit produced"
|
|
|
|
|
|
def test_run_task_fails_fast_without_credential(tmp_path):
|
|
repo = _init_repo(tmp_path)
|
|
task_file = _task_file(tmp_path, repo)
|
|
|
|
with patch("rein_openweights.runner.resolve_openrouter_api_key", return_value=None):
|
|
result = run_task(task_file, report_to_hub=False)
|
|
|
|
assert result.ok is False
|
|
assert "credential" in result.reason
|
|
|
|
|
|
def test_run_task_refuses_unknown_tool_profile_before_credential_lookup(tmp_path):
|
|
repo = _init_repo(tmp_path)
|
|
task_file = _task_file(tmp_path, repo)
|
|
|
|
with patch("rein_openweights.runner.resolve_openrouter_api_key") as resolve:
|
|
result = run_task(task_file, tool_profile="unsafe-shell", report_to_hub=False)
|
|
|
|
assert result.ok is False
|
|
assert result.reason == "unsupported tool profile: unsafe-shell"
|
|
assert result.tool_profile == "unsafe-shell"
|
|
resolve.assert_not_called()
|
|
|
|
|
|
def test_run_task_normalizes_provider_failure(tmp_path):
|
|
repo = _init_repo(tmp_path)
|
|
task_file = _task_file(tmp_path, repo)
|
|
|
|
with (
|
|
patch("rein_openweights.runner.resolve_openrouter_api_key", return_value="sk-test"),
|
|
patch("rein_openweights.runner.run_loop", side_effect=RuntimeError("provider down")),
|
|
):
|
|
result = run_task(task_file, report_to_hub=False)
|
|
|
|
assert result.ok is False
|
|
assert result.committed is False
|
|
assert result.reason == "session failed: provider down"
|
|
assert result.model
|