Introduce Devii agents subsystem with supervisor, policy, and evals

- Add agents package: controller, runner, store, tools, actions, evals, policy
- Wire agents into Devii service, session, registry, CLI, and dispatcher
- Extend database schema and config for agent persistence
- Add news and telegram bridge updates plus landing UI and docs
- Cover agents, news, and telegram flows with unit tests
This commit is contained in:
2026-10-26 02:54:44 +01:00
parent 407673bf57
commit 3bfde87fdb
50 changed files with 4102 additions and 78 deletions
+133
View File
@@ -0,0 +1,133 @@
# retoor <retoor@molodetz.nl>
import json
from devplacepy.services.devii.agents.runner import AgentRunner
from devplacepy.services.devii.cost.tracker import CostTracker, Pricing
from tests.conftest import run_async
class _Ledger:
def __init__(self):
self.spent = 0.0
def spent_24h(self, owner_kind, owner_id):
return self.spent
class _Settings:
daily_limit_usd = 1.0
plan_required = True
verify_required = True
class _StubSession:
def __init__(self):
self.cost = CostTracker(pricing=Pricing())
self.settings = _Settings()
self._ledger = _Ledger()
self._llm = None
self.dispatcher = None
self.owner_kind = "user"
self.owner_id = "owner-1"
def _runner(**overrides):
args = {
"session": _StubSession(),
"uid": "run-1",
"label": "run",
"category_key": "research",
"effort": "standard",
"task": "Compare static site generators.",
"output_format": "A markdown table.",
"tools": [],
"task_scope": False,
}
args.update(overrides)
return AgentRunner(**args)
def _ask_call(call_id, question):
return {
"id": call_id,
"function": {"name": "ask_user", "arguments": json.dumps({"question": question})},
}
def test_system_prompt_carries_contract_and_behavior():
runner = _runner(behavior_text="Be terse.")
prompt = runner.messages[0]["content"]
assert "no browser" in prompt
assert "ask_user" in prompt
assert "Be terse." in prompt
assert "Compare static site generators." in prompt
assert "A markdown table." in prompt
def test_pending_ask_found_and_answered():
runner = _runner()
runner.messages.append(
{"role": "assistant", "content": "", "tool_calls": [_ask_call("c1", "Budget?")]}
)
runner.messages.append(
{
"role": "tool",
"tool_call_id": "c1",
"name": "ask_user",
"content": json.dumps({"status": "paused_for_user"}),
}
)
assert runner._pending_ask() == ("c1", "Budget?")
runner.apply_answer("zero")
assert runner._pending_ask() is None
assert runner.messages[-1]["content"] == "The user answered: zero"
def test_quota_spent_short_circuits_without_llm():
session = _StubSession()
session._ledger.spent = 5.0
runner = _runner(session=session)
outcome, text = run_async(runner.run_once())
assert outcome == "error"
assert "quota" in text
def test_trace_tracks_progress_and_streak():
runner = _runner()
runner._trace("call", "fetch_url", "example.com")
assert runner.tool_calls == 1
runner._trace("err", "fetch_url", "boom")
assert runner.error_streak == 1
runner._trace("ok", "fetch_url", "")
assert runner.error_streak == 0
assert "fetch_url" in runner.progress_note
def test_task_scope_wraps_the_loop(monkeypatch):
from devplacepy.services.devii.tasks.context import in_task_run
seen = {}
async def fake_loop(**kwargs):
seen["scoped"] = in_task_run()
return "done"
monkeypatch.setattr(
"devplacepy.services.devii.agents.runner.react_loop", fake_loop
)
run_async(_runner(task_scope=True).run_once())
assert seen == {"scoped": True}
run_async(_runner(task_scope=False).run_once())
assert seen == {"scoped": False}
def test_counts_and_usage_start_at_zero():
runner = _runner()
assert runner.counts() == (0, 0, 0.0)
assert runner.usage() == {
"prompt_tokens": 0,
"completion_tokens": 0,
"cache_hit_tokens": 0,
"cache_miss_tokens": 0,
}