checkpoint: Working on getting gemini cli to actually have parity with gemini api.

This commit is contained in:
2026-02-26 00:31:33 -05:00
parent cbe359b1a5
commit a70680b2a2
14 changed files with 710 additions and 243 deletions

View File

@@ -13,6 +13,7 @@ during chat creation to avoid massive history bloat.
# ai_client.py
import tomllib
import json
import sys
import time
import datetime
import hashlib
@@ -267,7 +268,16 @@ def _classify_deepseek_error(exc: Exception) -> ProviderError:
def set_provider(provider: str, model: str):
global _provider, _model
_provider = provider
_model = model
if provider == "gemini_cli":
valid_models = _list_gemini_cli_models()
# If model is invalid or belongs to another provider (like deepseek), force default
if model not in valid_models or model.startswith("deepseek"):
_model = "gemini-3-flash-preview"
else:
_model = model
else:
_model = model
@@ -298,6 +308,7 @@ def reset_session():
_gemini_cache_created_at = None
if _gemini_cli_adapter:
_gemini_cli_adapter.session_id = None
_gemini_cli_adapter = None
_anthropic_client = None
with _anthropic_history_lock:
_anthropic_history = []
@@ -336,9 +347,26 @@ def list_models(provider: str) -> list[str]:
return _list_anthropic_models()
elif provider == "deepseek":
return _list_deepseek_models(creds["deepseek"]["api_key"])
elif provider == "gemini_cli":
return _list_gemini_cli_models()
return []
def _list_gemini_cli_models() -> list[str]:
"""
List available Gemini models for the CLI.
Since the CLI doesn't have a direct 'list models' command yet,
we return a curated list of supported models based on CLI metadata.
"""
return [
"gemini-3-flash-preview",
"gemini-3.1-pro-preview",
"gemini-2.5-pro",
"gemini-2.5-flash",
"gemini-2.5-flash-lite",
]
def _list_gemini_models(api_key: str) -> list[str]:
try:
@@ -844,33 +872,45 @@ def _send_gemini_cli(md_content: str, user_message: str, base_dir: str,
try:
if _gemini_cli_adapter is None:
_gemini_cli_adapter = GeminiCliAdapter(binary_path="gemini")
adapter = _gemini_cli_adapter
mcp_client.configure(file_items or [], [base_dir])
# If it's a new session (session_id is None), we should ideally send the context.
# Construct the system instruction, combining the base system prompt and the current context.
sys_instr = f"{_get_combined_system_prompt()}\n\n<context>\n{md_content}\n</context>"
safety_settings = [{'category': 'HARM_CATEGORY_DANGEROUS_CONTENT', 'threshold': 'BLOCK_ONLY_HIGH'}]
# Initial payload for the first message
payload = user_message
if _gemini_cli_adapter.session_id is None:
# Prepend context and discussion history to the first message
full_prompt = f"{_get_combined_system_prompt()}\n\n<context>\n{md_content}\n</context>\n\n"
if adapter.session_id is None:
if discussion_history:
full_prompt += f"[DISCUSSION HISTORY]\n\n{discussion_history}\n\n---\n\n"
full_prompt += user_message
payload = full_prompt
payload = f"[DISCUSSION HISTORY]\n\n{discussion_history}\n\n---\n\n{user_message}"
all_text = []
_cumulative_tool_bytes = 0
for r_idx in range(MAX_TOOL_ROUNDS + 2):
if adapter is None:
break
events.emit("request_start", payload={"provider": "gemini_cli", "model": _model, "round": r_idx})
_append_comms("OUT", "request", {"message": f"[CLI] [round {r_idx}] [msg {len(payload)}]"})
resp_data = _gemini_cli_adapter.send(payload)
resp_data = adapter.send(payload, safety_settings=safety_settings, system_instruction=sys_instr, model=_model)
# Log any stderr from the CLI for transparency
cli_stderr = resp_data.get("stderr", "")
if cli_stderr:
sys.stderr.write(f"\n--- Gemini CLI stderr ---\n{cli_stderr}\n-------------------------\n")
sys.stderr.flush()
txt = resp_data.get("text", "")
if txt: all_text.append(txt)
calls = resp_data.get("tool_calls", [])
usage = _gemini_cli_adapter.last_usage or {}
latency = _gemini_cli_adapter.last_latency
usage = adapter.last_usage or {}
latency = adapter.last_latency
events.emit("response_received", payload={"provider": "gemini_cli", "model": _model, "usage": usage, "latency": latency, "round": r_idx})