diff --git a/app/api/routes/device_ws.py b/app/api/routes/device_ws.py index 1260702..16a3b67 100644 --- a/app/api/routes/device_ws.py +++ b/app/api/routes/device_ws.py @@ -41,8 +41,8 @@ from sqlalchemy import update from app.api.routes.scout_setup import handle_journey_message, handle_journey_start from app.config.settings import settings -from app.core.agent_runner import trigger_pending_runs -from app.core.agent_session_buffer import session_buffer +from app.core.scout_runner import trigger_pending_runs +from app.core.scout_session_buffer import session_buffer from app.core.brief_agent import run_home_brief, run_project_brief from app.core.deep_agent import run_contextual_stream, run_home_stream, run_task_brief_research_stream from app.core.output_formatter import extract_canvas_block @@ -306,7 +306,7 @@ def get_session_buffer(user_id: str, session_id: str, channel: str = "contextual Defined at module level so tests can monkeypatch it. The channel kwarg is accepted for forward-compatibility. """ - from app.core.agent_session_buffer import ContextualBufferProxy # noqa: PLC0415 + from app.core.scout_session_buffer import ContextualBufferProxy # noqa: PLC0415 return ContextualBufferProxy(session_buffer, user_id, session_id) diff --git a/app/api/routes/scouts.py b/app/api/routes/scouts.py index 95de491..9d4bbb0 100644 --- a/app/api/routes/scouts.py +++ b/app/api/routes/scouts.py @@ -24,7 +24,7 @@ from pydantic import BaseModel from app.api.deps import get_current_user from app.billing.tier_manager import FEATURES -from app.core.agent_runner import is_agent_running, run_local_agent +from app.core.scout_runner import is_agent_running, run_local_agent from app.core.device_manager import device_manager from app.core.note_summarizer import generate_note_summary from app.db import get_session diff --git a/app/core/deep_agent.py b/app/core/deep_agent.py index 0f43efe..1a91c6b 100644 --- a/app/core/deep_agent.py +++ b/app/core/deep_agent.py @@ -18,7 +18,7 @@ from app.agents.project_agent import PROJECT_TOOLS from app.agents.relations_agent import make_query_relations_tool from app.agents.task_agent import TASK_TOOLS from app.agents.timeline_agent import TIMELINE_TOOLS -from app.core.agent_session_buffer import session_buffer +from app.core.scout_session_buffer import session_buffer from app.core.langfuse_client import compile_prompt, extract_usage, get_langfuse, get_prompt_or_fallback, langfuse_context from app.core.llm import get_agent_llm, model_for_agent from app.core.memory_middleware import MemoryMiddleware diff --git a/app/core/agent_registry.py b/app/core/scout_registry.py similarity index 100% rename from app/core/agent_registry.py rename to app/core/scout_registry.py diff --git a/app/core/agent_runner.py b/app/core/scout_runner.py similarity index 96% rename from app/core/agent_runner.py rename to app/core/scout_runner.py index 82b1679..f92a69b 100644 --- a/app/core/agent_runner.py +++ b/app/core/scout_runner.py @@ -169,7 +169,7 @@ def _is_overdue(schedule_cron: str, last_run_at: datetime | None) -> bool: next_run: datetime = cron.get_next(datetime) return now >= next_run except Exception as exc: - logger.warning("agent_runner: cannot parse cron %r: %s", schedule_cron, exc) + logger.warning("scout_runner: cannot parse cron %r: %s", schedule_cron, exc) return False @@ -290,7 +290,7 @@ async def _run_agent_with_tools( call_name = str(call.get("name", "")) call_args = call.get("args", {}) logger.info( - "agent_runner: tool_call name=%s args=%s", + "scout_runner: tool_call name=%s args=%s", call_name, json.dumps(call_args, ensure_ascii=True)[:800], ) @@ -305,7 +305,7 @@ async def _run_agent_with_tools( tool_output = await tool_fn.ainvoke(call_args) logger.info( - "agent_runner: tool_result name=%s output=%s", + "scout_runner: tool_result name=%s output=%s", call_name, str(tool_output)[:200], ) @@ -360,7 +360,7 @@ async def _scan_directories( try: result = await execute_on_client(action="list_directory", data={"path": path}) except Exception as exc: - logger.warning("agent_runner: list_directory failed %r: %s", path, exc) + logger.warning("scout_runner: list_directory failed %r: %s", path, exc) return for entry in result.get("entries", []): entry_path = entry.get("path", "") @@ -414,7 +414,7 @@ async def _fetch_projects() -> list[dict]: result = await execute_on_client(action="select", table="projects") return result.get("rows", []) except Exception as exc: - logger.warning("agent_runner: failed to fetch projects: %s", exc) + logger.warning("scout_runner: failed to fetch projects: %s", exc) return [] @@ -442,7 +442,7 @@ async def _fetch_domain_entities(domain: str, project_id: str) -> list[dict]: ) return result.get("rows", []) except Exception as exc: - logger.warning("agent_runner: failed to fetch %s: %s", domain, exc) + logger.warning("scout_runner: failed to fetch %s: %s", domain, exc) return [] @@ -586,7 +586,7 @@ async def run_local_agent( if not is_online: logger.info( - "agent_runner: skip run=%s — device %r offline for user=%s", + "scout_runner: skip run=%s — device %r offline for user=%s", run_id, target_device_id or "", user_id, @@ -616,7 +616,7 @@ async def run_local_agent( last_run_at=config.last_run_at, ) logger.info( - "agent_runner: run=%s found %d file(s) after filtering", run_id, len(file_paths) + "scout_runner: run=%s found %d file(s) after filtering", run_id, len(file_paths) ) if not file_paths: @@ -641,7 +641,7 @@ async def run_local_agent( raw_content: str = file_result.get("content", "") if not raw_content.strip(): logger.debug( - "agent_runner: run=%s skipping empty file %r", run_id, file_path + "scout_runner: run=%s skipping empty file %r", run_id, file_path ) continue @@ -651,7 +651,7 @@ async def run_local_agent( preprocessed = preprocess(content_type, raw_content) logger.info( - "agent_runner: run=%s file=%r content_type=%s clean_len=%d", + "scout_runner: run=%s file=%r content_type=%s clean_len=%d", run_id, file_path, content_type, len(preprocessed.clean_text), ) @@ -711,19 +711,19 @@ async def run_local_agent( projects_block = _format_projects(projects) logger.info( - "agent_runner: run=%s file=%r created=%d result=%s", + "scout_runner: run=%s file=%r created=%d result=%s", run_id, file_path, file_created, result_text[:200], ) except Exception as exc: errors.append(f"Error processing '{file_path}': {exc}") logger.error( - "agent_runner: run=%s file=%r failed: %s", run_id, file_path, exc + "scout_runner: run=%s file=%r failed: %s", run_id, file_path, exc ) except Exception as exc: errors.append(f"Agent run failed: {exc}") - logger.error("agent_runner: run=%s failed: %s", run_id, exc) + logger.error("scout_runner: run=%s failed: %s", run_id, exc) finally: _running_agents.discard(agent_id) clear_client_executor() @@ -744,7 +744,7 @@ async def run_local_agent( errors=errors, ) logger.info( - "agent_runner: run=%s done status=%s processed=%d created=%d errors=%d", + "scout_runner: run=%s done status=%s processed=%d created=%d errors=%d", run_id, final_status, items_processed, @@ -762,7 +762,7 @@ async def run_local_agent( }) except Exception as exc: logger.warning( - "agent_runner: run=%s failed to send run_complete: %s", run_id, exc + "scout_runner: run=%s failed to send run_complete: %s", run_id, exc ) @@ -797,7 +797,7 @@ async def run_cloud_agent( # ── 1. Device online check ───────────────────────────────────────── if not device_mgr.is_online(user_id): logger.info( - "agent_runner: skip cloud run=%s — no device online for user=%s", + "scout_runner: skip cloud run=%s — no device online for user=%s", run_id, user_id, ) @@ -822,7 +822,7 @@ async def run_cloud_agent( try: credentials_info = decrypt_token(config.oauth_token_encrypted) except ValueError as exc: - logger.error("agent_runner: failed to decrypt OAuth token for agent %s: %s", config.id, exc) + logger.error("scout_runner: failed to decrypt OAuth token for agent %s: %s", config.id, exc) await _finalize_run( run_log, status="error", @@ -868,7 +868,7 @@ async def run_cloud_agent( raw_messages = [] except RuntimeError as exc: logger.error( - "agent_runner: provider fetch failed for cloud agent %s: %s", config.id, exc + "scout_runner: provider fetch failed for cloud agent %s: %s", config.id, exc ) await _finalize_run( run_log, @@ -881,7 +881,7 @@ async def run_cloud_agent( return logger.info( - "agent_runner: cloud agent %s fetched %d item(s) from %s for user=%s", + "scout_runner: cloud agent %s fetched %d item(s) from %s for user=%s", config.id, len(raw_messages), config.provider, @@ -947,10 +947,10 @@ async def run_cloud_agent( if cfg_row: cfg_row.oauth_token_encrypted = new_encrypted await db.commit() - logger.debug("agent_runner: refreshed OAuth token persisted for agent %s", config.id) + logger.debug("scout_runner: refreshed OAuth token persisted for agent %s", config.id) except Exception as exc: logger.warning( - "agent_runner: failed to persist refreshed token for agent %s: %s", + "scout_runner: failed to persist refreshed token for agent %s: %s", config.id, exc, ) @@ -974,7 +974,7 @@ async def run_cloud_agent( config_type="cloud", ) logger.info( - "agent_runner: cloud run=%s done status=%s processed=%d created=%d errors=%d", + "scout_runner: cloud run=%s done status=%s processed=%d created=%d errors=%d", run_id, final_status, items_processed, @@ -996,7 +996,7 @@ async def trigger_pending_runs( Called as a background task from the device WS endpoint on ``device_hello``. """ logger.info( - "agent_runner: pending-run scan skipped for user=%s device=%s (client-owned agent config)", + "scout_runner: pending-run scan skipped for user=%s device=%s (client-owned agent config)", user_id, device_id, ) @@ -1047,5 +1047,5 @@ async def _finalize_run( await db.commit() except Exception as exc: logger.error( - "agent_runner: failed to finalize run_log=%s: %s", run_log.id, exc + "scout_runner: failed to finalize run_log=%s: %s", run_log.id, exc ) diff --git a/app/core/agent_session_buffer.py b/app/core/scout_session_buffer.py similarity index 100% rename from app/core/agent_session_buffer.py rename to app/core/scout_session_buffer.py diff --git a/tests/test_agent_runner_v2.py b/tests/test_agent_runner_v2.py index 346433a..4f90d51 100644 --- a/tests/test_agent_runner_v2.py +++ b/tests/test_agent_runner_v2.py @@ -35,7 +35,7 @@ from unittest.mock import AsyncMock, MagicMock, patch import pytest import yaml -from app.core.agent_runner import ( +from app.core.scout_runner import ( _format_metadata, _format_projects, _get_extraction_rules, @@ -271,7 +271,7 @@ async def test_2_9_device_offline(): run_log = _make_run_log(config.id) mgr = _make_manager(online=False) - with patch("app.core.agent_runner._finalize_run", new_callable=AsyncMock) as mock_fin: + with patch("app.core.scout_runner._finalize_run", new_callable=AsyncMock) as mock_fin: await run_local_agent(_USER_ID, config, run_log, mgr) _, kwargs = mock_fin.call_args @@ -295,8 +295,8 @@ async def test_2_10_empty_file(): projects=[_PROJECTS["alpha"]], ) - with patch("app.core.agent_runner._make_agent_executor", return_value=executor), \ - patch("app.core.agent_runner._finalize_run", new_callable=AsyncMock) as mock_fin: + with patch("app.core.scout_runner._make_agent_executor", return_value=executor), \ + patch("app.core.scout_runner._finalize_run", new_callable=AsyncMock) as mock_fin: await run_local_agent(_USER_ID, config, run_log, mgr) _, kwargs = mock_fin.call_args @@ -326,9 +326,9 @@ async def test_2_8_items_created_count(): _tool_calls_out.extend(["create_task", "create_note", "update_task"]) return "Done." - with patch("app.core.agent_runner._make_agent_executor", return_value=executor), \ - patch("app.core.agent_runner._run_agent_with_tools", side_effect=mock_run_agent), \ - patch("app.core.agent_runner._finalize_run", new_callable=AsyncMock) as mock_fin: + with patch("app.core.scout_runner._make_agent_executor", return_value=executor), \ + patch("app.core.scout_runner._run_agent_with_tools", side_effect=mock_run_agent), \ + patch("app.core.scout_runner._finalize_run", new_callable=AsyncMock) as mock_fin: await run_local_agent(_USER_ID, config, run_log, mgr) _, kwargs = mock_fin.call_args @@ -377,8 +377,8 @@ async def test_eval_runner(runner_case, pytestconfig): ) if lf else nullcontext() with obs_ctx as obs: - with patch("app.core.agent_runner._make_agent_executor", return_value=executor), \ - patch("app.core.agent_runner._finalize_run", new_callable=AsyncMock) as mock_fin: + with patch("app.core.scout_runner._make_agent_executor", return_value=executor), \ + patch("app.core.scout_runner._finalize_run", new_callable=AsyncMock) as mock_fin: await run_local_agent(_USER_ID, config, run_log, mgr) _, kwargs = mock_fin.call_args