Add opt-in /assistent/chat-eval for AssistentChat via Debug API.
Lets agents POST/GET a real Assistent turn (tunnel or SSH) without folding it into cheap /snapshot; documents VRAM/Sqlite side effects. Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
@@ -144,6 +144,13 @@ def test_debug_server_routes(monkeypatch, tmp_path):
|
||||
code, data = get("/openapi.json")
|
||||
assert "/assistent/extension" in data["paths"]
|
||||
assert "/assistent/api" in data["paths"]
|
||||
assert "/assistent/chat-eval" in data["paths"]
|
||||
assert "post" in data["paths"]["/assistent/chat-eval"]
|
||||
|
||||
code, data = get("/assistent/chat-eval")
|
||||
assert "ok" in data
|
||||
assert data.get("error") == debug_checks.SSH_UNAVAILABLE or not data.get("ok")
|
||||
assert "hints" in data
|
||||
|
||||
with pytest.raises(Exception):
|
||||
urllib.request.urlopen(f"http://127.0.0.1:{port}/nope", timeout=2)
|
||||
@@ -151,6 +158,105 @@ def test_debug_server_routes(monkeypatch, tmp_path):
|
||||
debug_api.stop_debug_server(srv)
|
||||
|
||||
|
||||
def test_extract_assistent_patch():
|
||||
from gpu_rent.debug_assistent import extract_assistent_patch
|
||||
|
||||
bare = extract_assistent_patch("просто текст без json")
|
||||
assert bare["patch"] is None
|
||||
assert "просто текст" in bare["prose"]
|
||||
|
||||
text = (
|
||||
"Ок, вот параметры:\n"
|
||||
"```json\n"
|
||||
'{"prompt":"a cat","steps":4,"cfg":1.0,"aspect":"1:1","actions":["generate"]}\n'
|
||||
"```\n"
|
||||
)
|
||||
got = extract_assistent_patch(text)
|
||||
assert got["patch"] is not None
|
||||
assert got["patch"]["steps"] == 4
|
||||
assert got["patch"]["cfg"] == 1.0
|
||||
assert got["patch"]["aspect"] == "1:1"
|
||||
assert got["patch"]["generate"] is True
|
||||
assert "Ок" in got["prose"]
|
||||
assert "```" not in got["prose"]
|
||||
|
||||
# last fence wins
|
||||
multi = (
|
||||
"```json\n{\"steps\":1}\n```\n"
|
||||
"mid\n"
|
||||
"```json\n{\"steps\":8,\"cfg\":2}\n```"
|
||||
)
|
||||
got2 = extract_assistent_patch(multi)
|
||||
assert got2["patch"]["steps"] == 8
|
||||
assert got2["patch"]["cfg"] == 2
|
||||
|
||||
|
||||
def test_chat_eval_mocked_http(monkeypatch, tmp_path):
|
||||
from gpu_rent import debug_assistent
|
||||
|
||||
_auth_env(monkeypatch, tmp_path)
|
||||
cfg = load_config(require_auth=True)
|
||||
|
||||
monkeypatch.setattr(
|
||||
debug_assistent,
|
||||
"_swarm_base",
|
||||
lambda cfg: ("http://127.0.0.1:17801", "local"),
|
||||
)
|
||||
monkeypatch.setattr(
|
||||
debug_assistent,
|
||||
"_session_id",
|
||||
lambda base: ("sess-1", None, 5.0),
|
||||
)
|
||||
|
||||
calls: list[tuple[str, dict]] = []
|
||||
|
||||
def fake_http(url, *, method="GET", body=None, timeout=12.0):
|
||||
if url.endswith("/API/AssistentListModels"):
|
||||
return True, {"preferred": "qwen3-vl:8b", "models": ["qwen3-vl:8b"]}, 10.0
|
||||
if url.endswith("/API/AssistentChat"):
|
||||
calls.append((url, body or {}))
|
||||
reply = (
|
||||
"Используй turbo.\n"
|
||||
'```json\n{"prompt":"portrait","steps":4,"cfg":1,"aspect":"3:4",'
|
||||
'"actions":["generate"]}\n```'
|
||||
)
|
||||
return True, {"success": True, "reply": reply, "model": "qwen3-vl:8b"}, 42.0
|
||||
return False, "unexpected " + url, 1.0
|
||||
|
||||
monkeypatch.setattr(debug_assistent, "_http_json", fake_http)
|
||||
|
||||
out = debug_assistent.run_assistent_chat_eval(
|
||||
cfg,
|
||||
message="какой checkpoint?",
|
||||
persona="leonid",
|
||||
timeout=60,
|
||||
)
|
||||
assert out["ok"] is True
|
||||
assert out["via"] == "local"
|
||||
assert out["model"] == "qwen3-vl:8b"
|
||||
assert out["preferred"] == "qwen3-vl:8b"
|
||||
assert out["persona"] == "leonid"
|
||||
assert out["patch"]["steps"] == 4
|
||||
assert out["patch"]["cfg"] == 1
|
||||
assert out["patch"]["aspect"] == "3:4"
|
||||
assert "turbo" in (out["reply_prose"] or "").lower() or "turbo" in (out["reply"] or "").lower()
|
||||
assert calls and calls[0][1]["session_id"] == "sess-1"
|
||||
assert calls[0][1]["messages"][0]["content"] == "какой checkpoint?"
|
||||
assert calls[0][1]["includeBase"] is True
|
||||
|
||||
|
||||
def test_chat_eval_timeout_clamp():
|
||||
from gpu_rent.debug_assistent import (
|
||||
MAX_CHAT_EVAL_TIMEOUT,
|
||||
MIN_CHAT_EVAL_TIMEOUT,
|
||||
_clamp_chat_eval_timeout,
|
||||
)
|
||||
|
||||
assert _clamp_chat_eval_timeout(5) == MIN_CHAT_EVAL_TIMEOUT
|
||||
assert _clamp_chat_eval_timeout(9999) == MAX_CHAT_EVAL_TIMEOUT
|
||||
assert _clamp_chat_eval_timeout("90") == 90.0
|
||||
|
||||
|
||||
def test_assistent_compact_and_roles_local(monkeypatch, tmp_path):
|
||||
from gpu_rent import debug_assistent
|
||||
|
||||
|
||||
Reference in New Issue
Block a user