diff --git a/backend/apps/agents/create_sdk_hooks.py b/backend/apps/agents/create_sdk_hooks.py index a05362a7..dbf60cef 100644 --- a/backend/apps/agents/create_sdk_hooks.py +++ b/backend/apps/agents/create_sdk_hooks.py @@ -98,11 +98,7 @@ def create_sdk_hooks( @typechecked async def post_tool_hook(input_data: dict, tool_use_id: str) -> Dict[str, Any]: - elapsed_ms: Optional[int] = None - if tool_use_id and tool_use_id in tool_start_times: - elapsed_ms = int((time.time() - tool_start_times.pop(tool_use_id)) * 1000) - - raw_response = input_data.get("tool_response", "") + raw_response: str = input_data.get("tool_response", "") if isinstance(raw_response, list) and raw_response: text_parts: List[str] = [ diff --git a/backend/apps/agents/session_store.py b/backend/apps/agents/session_store.py index 56c868bb..12bb8168 100644 --- a/backend/apps/agents/session_store.py +++ b/backend/apps/agents/session_store.py @@ -7,33 +7,41 @@ The agents subapp calls these functions during close/resume/startup/shutdown. import json import os from typing import List, Tuple, Optional +from backend.config.paths import DB_ROOT +from typeguard import typechecked -from backend.config.paths import SESSIONS_DIR +SESSIONS_DIR = os.path.join(DB_ROOT, "sessions") -def _path(session_id: str) -> str: +@typechecked +def p_path(session_id: str) -> str: return os.path.join(SESSIONS_DIR, f"{session_id}.json") +@typechecked def save(session_id: str, data: dict) -> None: os.makedirs(SESSIONS_DIR, exist_ok=True) - with open(_path(session_id), "w") as f: + with open(p_path(session_id), "w") as f: json.dump(data, f, indent=2) +@typechecked def load(session_id: str) -> Optional[dict]: - path = _path(session_id) + path: str = p_path(session_id) if not os.path.exists(path): return None with open(path) as f: return json.load(f) +@typechecked def delete(session_id: str) -> None: - path = _path(session_id) + path: str = p_path(session_id) if os.path.exists(path): os.remove(path) +# TODO: better type spec for the dict type +@typechecked def load_all() -> List[Tuple[str, dict]]: results: List[Tuple[str, dict]] = [] if not os.path.exists(SESSIONS_DIR): @@ -48,6 +56,8 @@ def load_all() -> List[Tuple[str, dict]]: return results +# TODO: better type spec for the whole damn thing +@typechecked def build_search_text(agent_data: dict, max_len: int = 5000) -> str: parts = [agent_data.get("name", "")] for msg in agent_data.get("messages", {}).get("messages", []): @@ -57,24 +67,25 @@ def build_search_text(agent_data: dict, max_len: int = 5000) -> str: parts.append(content) return " ".join(parts)[:max_len] - +# TODO: all the dict get guesswork shld be swapped to smthn less ambiguous/guessy +@typechecked def get_history( q: str = "", limit: int = 20, offset: int = 0, dashboard_id: Optional[str] = None, ) -> dict: - all_data = load_all() + all_data: List[Tuple[str, dict]] = load_all() all_data.sort(key=lambda pair: pair[1].get("closed_at") or "", reverse=True) - q_lower = q.strip().lower() + q_lower: str = q.strip().lower() history: List[dict] = [] for sid, data in all_data: if dashboard_id and data.get("dashboard_id") != dashboard_id: continue if q_lower: - name = (data.get("name") or "").lower() - search_text = (data.get("search_text") or "").lower() + name: str = (data.get("name") or "").lower() + search_text: str = (data.get("search_text") or "").lower() if q_lower not in name and q_lower not in search_text: continue history.append({ @@ -89,11 +100,12 @@ def get_history( "dashboard_id": data.get("dashboard_id"), }) - total = len(history) - page = history[offset : offset + limit] + total: int = len(history) + page: List[dict] = history[offset : offset + limit] return {"sessions": page, "total": total, "has_more": offset + limit < total} +@typechecked async def reconcile_on_startup() -> None: for sid, data in load_all(): if data.get("status") in ("running", "waiting_approval"):