fix for gemini.

This commit is contained in:
2026-02-22 11:41:11 -05:00
parent 4755f4b590
commit 8bf95866dc

View File

@@ -453,6 +453,18 @@ def _ensure_gemini_client():
_gemini_client = genai.Client(api_key=creds["gemini"]["api_key"]) _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: def _send_gemini(md_content: str, user_message: str, base_dir: str, file_items: list[dict] | None = None) -> str:
global _gemini_chat, _gemini_cache global _gemini_chat, _gemini_cache
from google.genai import types 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) current_md_hash = hash(md_content)
old_history = None old_history = None
if _gemini_chat and getattr(_gemini_chat, "_last_md_hash", None) != current_md_hash: 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: if _gemini_cache:
try: _gemini_client.caches.delete(name=_gemini_cache.name) try: _gemini_client.caches.delete(name=_gemini_cache.name)
except: pass 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): for r_idx in range(MAX_TOOL_ROUNDS + 2):
# Strip stale file refreshes and truncate old tool outputs in Gemini history # Strip stale file refreshes and truncate old tool outputs in Gemini history
if _gemini_chat and _gemini_chat.history: if _gemini_chat and _get_gemini_history_list(_gemini_chat):
for msg in _gemini_chat.history: for msg in _get_gemini_history_list(_gemini_chat):
if msg.role == "user" and hasattr(msg, "parts"): if msg.role == "user" and hasattr(msg, "parts"):
for p in msg.parts: for p in msg.parts:
if hasattr(p, "function_response") and p.function_response and hasattr(p.function_response, "response"): 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 # Guard: if Gemini reports input tokens approaching the limit, drop oldest history pairs
total_in = usage.get("input_tokens", 0) total_in = usage.get("input_tokens", 0)
if total_in > _GEMINI_MAX_INPUT_TOKENS and _gemini_chat and _gemini_chat.history: if total_in > _GEMINI_MAX_INPUT_TOKENS and _gemini_chat and _get_gemini_history_list(_gemini_chat):
hist = _gemini_chat.history hist = _get_gemini_history_list(_gemini_chat)
dropped = 0 dropped = 0
# Drop oldest pairs (user+model) but keep at least the last 2 entries # 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: 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 saved = 0
for p in hist[0].parts: for _ in range(2):
if hasattr(p, "text") and p.text: if not hist: break
saved += len(p.text) // 4 for p in hist[0].parts:
elif hasattr(p, "function_response") and p.function_response: if hasattr(p, "text") and p.text:
r = getattr(p.function_response, "response", {}) saved += len(p.text) // 4
if isinstance(r, dict): elif hasattr(p, "function_response") and p.function_response:
saved += len(str(r.get("output", ""))) // 4 r = getattr(p.function_response, "response", {})
hist.pop(0) if isinstance(r, dict):
total_in -= max(saved, 100) saved += len(str(r.get("output", ""))) // 4
dropped += 1 hist.pop(0)
dropped += 1
total_in -= max(saved, 200)
if dropped > 0: if dropped > 0:
_append_comms("OUT", "request", {"message": f"[GEMINI HISTORY TRIMMED: dropped {dropped} old entries to stay within token budget]"}) _append_comms("OUT", "request", {"message": f"[GEMINI HISTORY TRIMMED: dropped {dropped} old entries to stay within token budget]"})