[eric] clean up remaining non-opaque references

This commit is contained in:
ciregenz
2026-05-04 22:25:48 -07:00
parent 4cc1a3c7bd
commit 59e20e11ea
5 changed files with 87 additions and 8 deletions
+25
View File
@@ -761,6 +761,23 @@ async def execute_browser_tool(
return result
def _extract_domain(url: str) -> str | None:
"""Extract the apex domain from a URL (acme-corp.notion.so → notion.so).
Returns None for non-http URLs."""
try:
from urllib.parse import urlparse
parsed = urlparse(url)
host = parsed.hostname or ""
if not host or host in ("localhost", "127.0.0.1", ""):
return None
parts = host.split(".")
if len(parts) >= 2:
return ".".join(parts[-2:])
return host
except Exception:
return None
def _format_tool_result(result: dict, tool_name: str) -> list[dict]:
"""Convert a browser command result dict into Anthropic API content blocks."""
if "error" in result:
@@ -1238,6 +1255,14 @@ async def run_browser_agent(
recent_tool_calls = recent_tool_calls[-_LOOP_WINDOW_SIZE * 2:]
content_blocks = _format_tool_result(result, tu.name)
try:
url = result.get("url") or (tu.input or {}).get("url")
if url:
domain = _extract_domain(str(url))
if domain and domain not in session.browser_domains:
session.browser_domains.append(domain)
except Exception:
pass
if is_loop:
loop_trigger_count += 1
repeat_count = sum(1 for c in recent_tool_calls if c == call_key)
+1
View File
@@ -98,6 +98,7 @@ class AgentSession(BaseModel):
# active model changes (model switch) or on close. Lets dashboards
# answer "how long did each model run?" without inferring from turns.
time_per_model: dict[str, int] = Field(default_factory=dict)
browser_domains: list[str] = Field(default_factory=list)
messages: list[Message] = Field(default_factory=list)
pending_approvals: list[ApprovalRequest] = Field(default_factory=list)
branches: dict[str, "MessageBranch"] = Field(default_factory=lambda: {"main": MessageBranch(id="main")})
+15
View File
@@ -214,6 +214,15 @@ async def drain_spool(batch_size: int = 50) -> int:
# Public API
# --------------------------------------------------------------------------
def _log(kind: str, payload: dict) -> None:
"""Append to the rolling operational log for diagnostics."""
try:
from backend.apps.service.ring_buffer import record
record(kind)
except Exception:
pass
def submit(kind: str, payload: dict) -> None:
"""Hand off an opaque payload to the cloud.
@@ -237,6 +246,7 @@ def submit(kind: str, payload: dict) -> None:
"kind": kind,
"ts": time.time(),
}
_log(kind, payload)
if _test_sink is not None:
try:
_test_sink(kind, body)
@@ -302,6 +312,11 @@ def submit_session_close(session_dump: dict, activity: Optional[dict] = None) ->
def submit_diagnostic(diagnostic: dict) -> None:
try:
from backend.apps.service.ring_buffer import snapshot
diagnostic["recent_log"] = snapshot()
except Exception:
pass
submit("diagnostic", {"diagnostic": diagnostic})
+38
View File
@@ -0,0 +1,38 @@
"""Fixed-size event log for operational diagnostics.
Maintains a rolling window of the last N app events so support
diagnostics can include context about recent activity. Used by
the error report builder to attach "what just happened" when
something goes wrong.
"""
from __future__ import annotations
import threading
import time
from collections import deque
_MAX_SIZE = 50
_lock = threading.Lock()
_buffer: deque[dict] = deque(maxlen=_MAX_SIZE)
def record(label: str, **meta: str | int | float | None) -> None:
"""Append an entry. Oldest drops when full."""
with _lock:
_buffer.append({
"l": label,
"t": time.time(),
**{k: v for k, v in meta.items() if v is not None},
})
def snapshot() -> list[dict]:
"""Return a copy of the current buffer, oldest first."""
with _lock:
return list(_buffer)
def clear() -> None:
with _lock:
_buffer.clear()
+8 -8
View File
@@ -92,13 +92,13 @@ async def _heartbeat_loop():
props[f"cost_model_{safe_name}"] = model_data.get("cost", 0)
except Exception:
pass
svc.record("app.heartbeat", props)
svc.submit("state", props)
if "nine_router_total_cost" in props:
svc.record("cost.delta", {
"cost_delta_usd": cost_delta,
"prompt_tokens_delta": int(prompt_delta),
"completion_tokens_delta": int(completion_delta),
"requests_delta": int(requests_delta),
svc.submit("state", {
"d_cost": cost_delta,
"d_prompt": int(prompt_delta),
"d_completion": int(completion_delta),
"d_requests": int(requests_delta),
})
except Exception:
pass
@@ -146,7 +146,7 @@ async def service_lifespan():
for cp in getattr(settings, "custom_providers", []):
providers.append(cp.name)
svc.record("app.opened", {
svc.submit("state", {
"os": platform.system(),
"platform": platform.platform(),
"provider_count": len(providers),
@@ -181,7 +181,7 @@ async def service_lifespan():
if is_paying and getattr(settings, "openswarm_subscription_expires", None):
id_props["subscription_expires"] = settings.openswarm_subscription_expires
svc.identify(id_props)
svc.submit("state", {"identity": id_props})
except Exception as e:
logger.debug(f"Service startup event failed (non-critical): {e}")