diff --git a/ai_client.py b/ai_client.py index cd6d8f4..2897c2d 100644 --- a/ai_client.py +++ b/ai_client.py @@ -18,7 +18,7 @@ import datetime from pathlib import Path import file_cache import mcp_client -import google.genai +from google import genai from google.genai import types from events import EventEmitter @@ -276,9 +276,9 @@ def list_models(provider: str) -> list[str]: def _list_gemini_models(api_key: str) -> list[str]: - # from google import genai # Removed + try: - client = google.genai.Client(api_key=api_key) + client = genai.Client(api_key=api_key) models = [] for m in client.models.list(): name = m.name @@ -370,7 +370,7 @@ def _get_anthropic_tools() -> list[dict]: def _gemini_tool_declaration(): - # from google.genai import types # Removed + declarations = [] @@ -380,15 +380,17 @@ def _gemini_tool_declaration(): continue props = {} for pname, pdef in spec["parameters"].get("properties", {}).items(): - props[pname] = google.genai.types.Schema( - type=google.genai.types.Type.STRING, + ptype_str = pdef.get("type", "string").upper() + ptype = getattr(types.Type, ptype_str, types.Type.STRING) + props[pname] = types.Schema( + type=ptype, description=pdef.get("description", ""), ) - declarations.append(google.genai.types.FunctionDeclaration( + declarations.append(types.FunctionDeclaration( name=spec["name"], description=spec["description"], - parameters=google.genai.types.Schema( - type=google.genai.types.Type.OBJECT, + parameters=types.Schema( + type=types.Type.OBJECT, properties=props, required=spec["parameters"].get("required", []), ), @@ -396,7 +398,7 @@ def _gemini_tool_declaration(): # PowerShell tool if _agent_tools.get(TOOL_NAME, True): - declarations.append(google.genai.types.FunctionDeclaration( + declarations.append(types.FunctionDeclaration( name=TOOL_NAME, description=( "Run a PowerShell script within the project base_dir. " @@ -404,11 +406,11 @@ def _gemini_tool_declaration(): "The working directory is set to base_dir automatically. " "stdout and stderr are returned to you as the result." ), - parameters=google.genai.types.Schema( - type=google.genai.types.Type.OBJECT, + parameters=types.Schema( + type=types.Type.OBJECT, properties={ - "script": google.genai.types.Schema( - type=google.genai.types.Type.STRING, + "script": types.Schema( + type=types.Type.STRING, description="The PowerShell script to execute." ) }, @@ -416,7 +418,7 @@ def _gemini_tool_declaration(): ), )) - return google.genai.types.Tool(function_declarations=declarations) if declarations else None + return types.Tool(function_declarations=declarations) if declarations else None def _run_script(script: str, base_dir: str) -> str: @@ -511,9 +513,8 @@ def _content_block_to_dict(block) -> dict: def _ensure_gemini_client(): global _gemini_client if _gemini_client is None: - # from google import genai # Removed creds = _load_credentials() - _gemini_client = google.genai.Client(api_key=creds["gemini"]["api_key"]) + _gemini_client = genai.Client(api_key=creds["gemini"]["api_key"]) @@ -530,7 +531,7 @@ def _get_gemini_history_list(chat): def _send_gemini(md_content: str, user_message: str, base_dir: str, file_items: list[dict] | None = None) -> str: global _gemini_chat, _gemini_cache, _gemini_cache_md_hash, _gemini_cache_created_at - # from google.genai import types # Removed + try: _ensure_gemini_client(); mcp_client.configure(file_items or [], [base_dir]) sys_instr = f"{_get_combined_system_prompt()}\n\n\n{md_content}\n" @@ -563,29 +564,29 @@ def _send_gemini(md_content: str, user_message: str, base_dir: str, file_items: _append_comms("OUT", "request", {"message": f"[CACHE TTL] Rebuilding cache (expired after {int(elapsed)}s)..."}) if not _gemini_chat: - chat_config = google.genai.types.GenerateContentConfig( + chat_config = types.GenerateContentConfig( system_instruction=sys_instr, tools=tools_decl, temperature=_temperature, max_output_tokens=_max_tokens, - safety_settings=[google.genai.types.SafetySetting(category="HARM_CATEGORY_DANGEROUS_CONTENT", threshold="BLOCK_ONLY_HIGH")] + safety_settings=[types.SafetySetting(category="HARM_CATEGORY_DANGEROUS_CONTENT", threshold="BLOCK_ONLY_HIGH")] ) try: # Gemini requires 1024 (Flash) or 4096 (Pro) tokens to cache. _gemini_cache = _gemini_client.caches.create( model=_model, - config=google.genai.types.CreateCachedContentConfig( + config=types.CreateCachedContentConfig( system_instruction=sys_instr, tools=tools_decl, ttl=f"{_GEMINI_CACHE_TTL}s", ) ) _gemini_cache_created_at = time.time() - chat_config = google.genai.types.GenerateContentConfig( + chat_config = types.GenerateContentConfig( cached_content=_gemini_cache.name, temperature=_temperature, max_output_tokens=_max_tokens, - safety_settings=[google.genai.types.SafetySetting(category="HARM_CATEGORY_DANGEROUS_CONTENT", threshold="BLOCK_ONLY_HIGH")] + safety_settings=[types.SafetySetting(category="HARM_CATEGORY_DANGEROUS_CONTENT", threshold="BLOCK_ONLY_HIGH")] ) _append_comms("OUT", "request", {"message": f"[CACHE CREATED] {_gemini_cache.name}"}) except Exception as e: diff --git a/conductor/tracks/api_vendor_alignment_20260223/plan.md b/conductor/tracks/api_vendor_alignment_20260223/plan.md index 71f50b3..828f852 100644 --- a/conductor/tracks/api_vendor_alignment_20260223/plan.md +++ b/conductor/tracks/api_vendor_alignment_20260223/plan.md @@ -1,6 +1,6 @@ # Implementation Plan: API Usage Audit and Alignment -## Phase 1: Research and Comprehensive Audit +## Phase 1: Research and Comprehensive Audit [checkpoint: 5ec4283] Identify all points of interaction with AI SDKs and compare them with latest official documentation. - [x] Task: List and categorize all AI SDK usage in the project. @@ -12,24 +12,24 @@ Identify all points of interaction with AI SDKs and compare them with latest off - [x] Verify latest patterns for Tool/Function calling. - [x] Task: Conductor - User Manual Verification 'Phase 1: Research and Comprehensive Audit' (Protocol in workflow.md) -## Phase 2: Gemini (google-genai) Alignment +## Phase 2: Gemini (google-genai) Alignment [checkpoint: 3d7a8b9] Align Gemini integration with documented best practices. -- [~] Task: Refactor Gemini Client and Chat initialization if needed. - - [ ] Write Tests - - [ ] Implement Feature -- [ ] Task: Optimize Gemini Context Caching. - - [ ] Write Tests - - [ ] Implement Feature -- [ ] Task: Align Gemini Tool Declaration and handling. - - [ ] Write Tests - - [ ] Implement Feature -- [ ] Task: Conductor - User Manual Verification 'Phase 2: Gemini (google-genai) Alignment' (Protocol in workflow.md) +- [x] Task: Refactor Gemini Client and Chat initialization if needed. + - [x] Write Tests + - [x] Implement Feature +- [x] Task: Optimize Gemini Context Caching. + - [x] Write Tests + - [x] Implement Feature +- [x] Task: Align Gemini Tool Declaration and handling. + - [x] Write Tests + - [x] Implement Feature +- [x] Task: Conductor - User Manual Verification 'Phase 2: Gemini (google-genai) Alignment' (Protocol in workflow.md) ## Phase 3: Anthropic Alignment Align Anthropic integration with documented best practices. -- [ ] Task: Refactor Anthropic Client and Message creation if needed. +- [~] Task: Refactor Anthropic Client and Message creation if needed. - [ ] Write Tests - [ ] Implement Feature - [ ] Task: Optimize Anthropic Prompt Caching (`cache_control`).