From 8bf95866dc79510d94d8fe09338df17744f834d4 Mon Sep 17 00:00:00 2001 From: Ed_ Date: Sun, 22 Feb 2026 11:41:11 -0500 Subject: [PATCH] fix for gemini. --- ai_client.py | 46 ++++++++++++++++++++++++++++++---------------- 1 file changed, 30 insertions(+), 16 deletions(-) diff --git a/ai_client.py b/ai_client.py index 380006a..c32a4a1 100644 --- a/ai_client.py +++ b/ai_client.py @@ -453,6 +453,18 @@ def _ensure_gemini_client(): _gemini_client = genai.Client(api_key=creds["gemini"]["api_key"]) + +def _get_gemini_history_list(chat): + if not chat: return [] + # google-genai SDK stores the mutable list in _history + if hasattr(chat, "_history"): + return chat._history + if hasattr(chat, "history"): + return chat.history + if hasattr(chat, "get_history"): + return chat.get_history() + return [] + def _send_gemini(md_content: str, user_message: str, base_dir: str, file_items: list[dict] | None = None) -> str: global _gemini_chat, _gemini_cache from google.genai import types @@ -465,7 +477,7 @@ def _send_gemini(md_content: str, user_message: str, base_dir: str, file_items: current_md_hash = hash(md_content) old_history = None if _gemini_chat and getattr(_gemini_chat, "_last_md_hash", None) != current_md_hash: - old_history = list(_gemini_chat.history) if _gemini_chat.history else [] + old_history = list(_get_gemini_history_list(_gemini_chat)) if _get_gemini_history_list(_gemini_chat) else [] if _gemini_cache: try: _gemini_client.caches.delete(name=_gemini_cache.name) except: pass @@ -513,8 +525,8 @@ def _send_gemini(md_content: str, user_message: str, base_dir: str, file_items: for r_idx in range(MAX_TOOL_ROUNDS + 2): # Strip stale file refreshes and truncate old tool outputs in Gemini history - if _gemini_chat and _gemini_chat.history: - for msg in _gemini_chat.history: + if _gemini_chat and _get_gemini_history_list(_gemini_chat): + for msg in _get_gemini_history_list(_gemini_chat): if msg.role == "user" and hasattr(msg, "parts"): for p in msg.parts: if hasattr(p, "function_response") and p.function_response and hasattr(p.function_response, "response"): @@ -543,23 +555,25 @@ def _send_gemini(md_content: str, user_message: str, base_dir: str, file_items: # Guard: if Gemini reports input tokens approaching the limit, drop oldest history pairs total_in = usage.get("input_tokens", 0) - if total_in > _GEMINI_MAX_INPUT_TOKENS and _gemini_chat and _gemini_chat.history: - hist = _gemini_chat.history + if total_in > _GEMINI_MAX_INPUT_TOKENS and _gemini_chat and _get_gemini_history_list(_gemini_chat): + hist = _get_gemini_history_list(_gemini_chat) dropped = 0 # Drop oldest pairs (user+model) but keep at least the last 2 entries while len(hist) > 4 and total_in > _GEMINI_MAX_INPUT_TOKENS * 0.7: - # Rough estimate: each dropped message saves ~(chars/4) tokens + # Drop in pairs (user + model) to maintain alternating roles required by Gemini saved = 0 - for p in hist[0].parts: - if hasattr(p, "text") and p.text: - saved += len(p.text) // 4 - elif hasattr(p, "function_response") and p.function_response: - r = getattr(p.function_response, "response", {}) - if isinstance(r, dict): - saved += len(str(r.get("output", ""))) // 4 - hist.pop(0) - total_in -= max(saved, 100) - dropped += 1 + for _ in range(2): + if not hist: break + for p in hist[0].parts: + if hasattr(p, "text") and p.text: + saved += len(p.text) // 4 + elif hasattr(p, "function_response") and p.function_response: + r = getattr(p.function_response, "response", {}) + if isinstance(r, dict): + saved += len(str(r.get("output", ""))) // 4 + hist.pop(0) + dropped += 1 + total_in -= max(saved, 200) if dropped > 0: _append_comms("OUT", "request", {"message": f"[GEMINI HISTORY TRIMMED: dropped {dropped} old entries to stay within token budget]"})