mirror of
https://github.com/openswarm-ai/openswarm.git
synced 2026-08-24 21:42:22 +02:00
[eric] browser: fire the learning self-audit every 25 finished tasks in a daemon thread (zero hot-path latency)
This commit is contained in:
@@ -22,6 +22,7 @@ import json
|
||||
import logging
|
||||
import os
|
||||
import re
|
||||
import threading
|
||||
import time
|
||||
from collections import Counter
|
||||
|
||||
@@ -191,4 +192,30 @@ def record_task(session_id, browser_id, task, status, started_at, turns,
|
||||
f"tools={len(action_log)} tok_in={summary['tokens_in']} tok_out={summary['tokens_out']} "
|
||||
f"recurring_errs={summary['recurring_errors'][:2]}"
|
||||
)
|
||||
_maybe_self_audit()
|
||||
return summary
|
||||
|
||||
|
||||
_AUDIT_EVERY_N = 25 # refresh the learning self-audit roughly this often
|
||||
_task_count = 0
|
||||
|
||||
|
||||
def _maybe_self_audit() -> None:
|
||||
"""Every N finished tasks, refresh the self-audit report in a daemon thread so
|
||||
it never adds latency to a run (the audit is ~3ms but stays off the hot path).
|
||||
Proposal-only: it writes a report a human reads, it changes nothing."""
|
||||
global _task_count
|
||||
_task_count += 1
|
||||
if _task_count % _AUDIT_EVERY_N != 0:
|
||||
return
|
||||
|
||||
def _run():
|
||||
try:
|
||||
from backend.apps.agents.browser import browser_self_audit
|
||||
browser_self_audit.run_and_write()
|
||||
except Exception:
|
||||
pass
|
||||
try:
|
||||
threading.Thread(target=_run, name="browser-self-audit", daemon=True).start()
|
||||
except Exception:
|
||||
pass
|
||||
|
||||
@@ -60,6 +60,32 @@ def test_clean_history_proposes_nothing():
|
||||
assert "learning cleanly" in audit.render_report(r)
|
||||
|
||||
|
||||
def test_audit_fires_every_n_finished_tasks(monkeypatch, tmp_path):
|
||||
# the trigger refreshes the report once every N tasks, off the hot path. Make
|
||||
# threads synchronous so the test is deterministic, and use a small N.
|
||||
from backend.apps.agents.browser import browser_metrics as m
|
||||
monkeypatch.setenv("OPENSWARM_BROWSER_METRICS_DIR", str(tmp_path))
|
||||
m._metrics_dir_cache = None
|
||||
m._task_count = 0
|
||||
monkeypatch.setattr(m, "_AUDIT_EVERY_N", 5)
|
||||
|
||||
class _SyncThread:
|
||||
def __init__(self, target=None, **kw):
|
||||
self._t = target
|
||||
|
||||
def start(self):
|
||||
self._t()
|
||||
monkeypatch.setattr(m.threading, "Thread", _SyncThread)
|
||||
|
||||
log = [{"tool": "BrowserClickIndex", "elapsed_ms": 5, "result_summary": "ok"}]
|
||||
report = tmp_path / "self_audit_report.md"
|
||||
for i in range(4):
|
||||
m.record_task(f"s{i}", "b1", "t", "completed", 0, 7, log, {})
|
||||
assert not report.exists(), "audit fired before N tasks"
|
||||
m.record_task("s5", "b1", "t", "completed", 0, 7, log, {})
|
||||
assert report.exists(), "audit did not fire at the Nth task"
|
||||
|
||||
|
||||
def test_run_and_write_emits_a_report_file_and_never_raises():
|
||||
d = tempfile.mkdtemp()
|
||||
_write(d, "tasks.jsonl", [])
|
||||
|
||||
Reference in New Issue
Block a user