from google import genai from google.genai import types import json from config import GEMINI_API_KEY _client = genai.Client(api_key=GEMINI_API_KEY) _DEFAULT_MODEL = "gemini-3-flash-preview" class BaseAgent: def __init__(self, system_prompt: str, model_name: str = _DEFAULT_MODEL): self.system_prompt = system_prompt self.model_name = model_name async def call(self, user_prompt: str, context: dict = None) -> dict: """Call Gemini asynchronously and always return a dict.""" full_prompt = user_prompt if context: full_prompt = f"CONTEXT:\n{json.dumps(context, indent=2)}\n\nTASK:\n{user_prompt}" try: response = await _client.aio.models.generate_content( model=self.model_name, contents=full_prompt, config=types.GenerateContentConfig( system_instruction=self.system_prompt, response_mime_type="application/json", temperature=0.7, ), ) text = response.text.strip() # Fast path: response is already valid JSON try: result = json.loads(text) if isinstance(result, dict): return result return {"error": "Gemini returned non-dict JSON", "raw": text[:200]} except json.JSONDecodeError: pass # Fallback: extract the first {...} block from the text start = text.find("{") end = text.rfind("}") + 1 if start != -1 and end > start: try: result = json.loads(text[start:end]) if isinstance(result, dict): return result except json.JSONDecodeError: pass return {"error": "Could not parse JSON from Gemini response", "raw": text[:500]} except Exception as e: print(f"[BaseAgent] Gemini call failed: {e}") return {"error": str(e)}