mirror of
https://github.com/pewdiepie-archdaemon/odysseus.git
synced 2026-11-06 13:12:27 +01:00
fix(agent): close approval continuation gaps
This commit is contained in:
@@ -1,11 +1,18 @@
|
||||
"""Regression: skill helpers must tolerate a non-dict skill.
|
||||
"""Regressions for skill-test input and exact-approval boundaries.
|
||||
|
||||
_skill_test_task did `skill.get(...)` and _should_check_retrieval_precision did
|
||||
`skill.get("tags")`; a skill row that loaded as a bare string/None raised
|
||||
AttributeError. They now treat a non-dict as empty / not-applicable.
|
||||
"""
|
||||
import asyncio
|
||||
import json
|
||||
|
||||
import routes.skills_routes as skills_routes
|
||||
from routes.skills_routes import (
|
||||
_run_skill_test_job,
|
||||
_run_skill_test_once,
|
||||
_should_check_retrieval_precision,
|
||||
_skill_test_jobs,
|
||||
_skill_test_messages,
|
||||
_skill_test_task,
|
||||
)
|
||||
@@ -26,3 +33,80 @@ def test_skill_test_messages_keep_skill_text_untrusted_and_arm_gate():
|
||||
assert payload not in messages[0]["content"]
|
||||
assert messages[1]["metadata"]["trusted"] is False
|
||||
assert messages[1]["metadata"]["tool_gate_untrusted"] is True
|
||||
|
||||
|
||||
def test_autonomous_skill_test_reports_exact_approval_as_inconclusive(monkeypatch):
|
||||
approval = {
|
||||
"kind": "tool_approval",
|
||||
"approval_id": "opaque",
|
||||
"question": "Allow this exact action once?",
|
||||
}
|
||||
|
||||
async def fake_loop(*args, **kwargs):
|
||||
yield "data: " + json.dumps({
|
||||
"type": "tool_output",
|
||||
"tool": "bash",
|
||||
"output": "Waiting for an exact user approval.",
|
||||
"ask_user": approval,
|
||||
})
|
||||
|
||||
async def fail_eval(*args, **kwargs):
|
||||
raise AssertionError("approval pause must not be judged as a failed skill")
|
||||
|
||||
monkeypatch.setattr("src.agent_loop.stream_agent_loop", fake_loop)
|
||||
monkeypatch.setattr(skills_routes, "_eval_skill_run", fail_eval)
|
||||
|
||||
transcript, verdict = asyncio.run(_run_skill_test_once(
|
||||
"skill markdown",
|
||||
"task",
|
||||
"http://example.test",
|
||||
"model",
|
||||
None,
|
||||
"owner",
|
||||
))
|
||||
|
||||
assert "Waiting for an exact user approval" in transcript
|
||||
assert verdict["verdict"] == "inconclusive"
|
||||
assert verdict["approval_required"] is True
|
||||
|
||||
|
||||
def test_manual_skill_test_pauses_with_resumable_exact_approval(monkeypatch):
|
||||
approval = {
|
||||
"kind": "tool_approval",
|
||||
"approval_id": "opaque",
|
||||
"question": "Allow this exact action once?",
|
||||
}
|
||||
|
||||
async def fake_loop(*args, **kwargs):
|
||||
yield "data: " + json.dumps({
|
||||
"type": "tool_output",
|
||||
"tool": "bash",
|
||||
"output": "Waiting for an exact user approval.",
|
||||
"ask_user": approval,
|
||||
})
|
||||
|
||||
monkeypatch.setattr("src.agent_loop.stream_agent_loop", fake_loop)
|
||||
key = ("owner", "skill")
|
||||
_skill_test_jobs[key] = {
|
||||
"status": "running",
|
||||
"log": [],
|
||||
"verdict": None,
|
||||
}
|
||||
try:
|
||||
asyncio.run(_run_skill_test_job(
|
||||
key,
|
||||
"skill",
|
||||
"skill markdown",
|
||||
"task",
|
||||
"http://example.test",
|
||||
"model",
|
||||
None,
|
||||
"owner",
|
||||
))
|
||||
|
||||
job = _skill_test_jobs[key]
|
||||
assert job["status"] == "awaiting_approval"
|
||||
assert job["approval"] == approval
|
||||
assert "Waiting for an exact user approval" in "".join(job["_transcript"])
|
||||
finally:
|
||||
_skill_test_jobs.pop(key, None)
|
||||
|
||||
Reference in New Issue
Block a user