diff --git a/src/timmy/kimi_delegation.py b/src/timmy/kimi_delegation.py index 4b9b20ef..a59eb170 100644 --- a/src/timmy/kimi_delegation.py +++ b/src/timmy/kimi_delegation.py @@ -20,6 +20,19 @@ import logging import re from typing import Any +try: + import httpx as _httpx_module +except ImportError: # pragma: no cover + _httpx_module = None # type: ignore[assignment] + +try: + from config import settings +except ImportError: # pragma: no cover + settings = None # type: ignore[assignment] + +# Re-export httpx at module level so tests can patch timmy.kimi_delegation.httpx +httpx = _httpx_module + logger = logging.getLogger(__name__) # Label applied to issues that Kimi should pick up @@ -228,14 +241,10 @@ async def create_kimi_research_issue( Returns: Dict with `success`, `issue_number`, `issue_url`, and `error` keys. """ - try: - import httpx + if httpx is None: + return {"success": False, "error": "Missing dependency: httpx"} - from config import settings - except ImportError as exc: - return {"success": False, "error": f"Missing dependency: {exc}"} - - if not settings.gitea_enabled or not settings.gitea_token: + if settings is None or not settings.gitea_enabled or not settings.gitea_token: return { "success": False, "error": "Gitea integration not configured (no token or disabled).", @@ -317,14 +326,10 @@ async def poll_kimi_issue( Returns: Dict with `completed` bool, `state`, `body`, and `error` keys. """ - try: - import httpx + if httpx is None: + return {"completed": False, "error": "Missing dependency: httpx"} - from config import settings - except ImportError as exc: - return {"completed": False, "error": f"Missing dependency: {exc}"} - - if not settings.gitea_enabled or not settings.gitea_token: + if settings is None or not settings.gitea_enabled or not settings.gitea_token: return {"completed": False, "error": "Gitea not configured."} base_url = f"{settings.gitea_url}/api/v1" @@ -413,8 +418,6 @@ async def index_kimi_artifact( return {"success": False, "error": "Empty artifact — nothing to index."} try: - import asyncio - from timmy.memory_system import store_memory # store_memory is synchronous — wrap in thread to avoid blocking event loop @@ -452,14 +455,10 @@ async def extract_and_create_followups( logger.info("No action items found in artifact for issue #%s", source_issue_number) return {"success": True, "created": [], "error": None} - try: - import httpx + if httpx is None: + return {"success": False, "created": [], "error": "Missing dependency: httpx"} - from config import settings - except ImportError as exc: - return {"success": False, "created": [], "error": str(exc)} - - if not settings.gitea_enabled or not settings.gitea_token: + if settings is None or not settings.gitea_enabled or not settings.gitea_token: return { "success": False, "created": [], diff --git a/tests/timmy/test_kimi_delegation.py b/tests/timmy/test_kimi_delegation.py index 998dfd3a..3c6a066b 100644 --- a/tests/timmy/test_kimi_delegation.py +++ b/tests/timmy/test_kimi_delegation.py @@ -64,7 +64,7 @@ class TestSlugify: def test_special_characters_removed(self): from timmy.kimi_delegation import _slugify - assert _slugify("Research: AI & ML!") == "research-ai--ml" + assert _slugify("Research: AI & ML!") == "research-ai-ml" def test_underscores_become_dashes(self): from timmy.kimi_delegation import _slugify