# ai_client.py Style Convention Curation ## Overview Refactor `src/ai_client.py` (2522 lines) to align with `conductor/code_styleguides/python.md` conventions, following the pattern established in the recent `gui_2.py` refactor. ## Current State Audit (as of UNCOMMITTED) ### Already Implemented - 1-space indentation throughout - Type annotations on all functions - Thread-local helpers (`get_current_tier`, `set_current_tier`) as module-level functions - SDM tags on docstrings ### Gaps to Fill - `ProviderError` defined inside module (should be at module level per convention) - No `#region` blocks despite 2522-line size (violates python.md Section 14) - No logical section organization for 80+ functions - Error classifier functions (`_classify_*_error`) could use vertical alignment ## Goals 1. Move `ProviderError` to module level (proper exception class, justified) 2. Add `#region` blocks to organize functions into logical sections 3. Apply vertical compaction alignment to dense conditionals 4. Preserve all call sites and SDM tags ## Changes ### 1. Module-Level `ProviderError` Move from inline class definition to module level, before top-level functions: ```python class ProviderError(Exception): def __init__(self, provider: str, message: str, code: str | None = None): self.provider = provider self.message = message self.code = code def ui_message(self) -> str: return f"[{self.provider.upper()}] {self.message}" ``` Location: After imports, before first function (~line 300). ### 2. Region Block Organization Add `#region: Section Name` / `#endregion: Section Name` blocks: | Region | Functions | |--------|-----------| | `#region: Provider Configuration` | `set_provider`, `get_provider`, `set_model_params`, `list_models`, `_list_gemini_cli_models`, `_list_gemini_models`, `_list_anthropic_models`, `_list_deepseek_models`, `_list_minimax_models` | | `#region: Credentials & Setup` | `_get_proxy`, `get_credentials_path`, `_load_credentials`, `cleanup` | | `#region: System Prompt Management` | `set_custom_system_prompt`, `set_base_system_prompt`, `set_use_default_base_prompt`, `set_project_context_marker`, `_get_context_marker`, `_get_combined_system_prompt`, `get_combined_system_prompt` | | `#region: Comms Log` | `get_comms_log_callback`, `set_comms_log_callback`, `_append_comms`, `get_comms_log`, `clear_comms_log` | | `#region: Error Classification` | `_classify_anthropic_error`, `_classify_gemini_error`, `_classify_deepseek_error`, `_classify_minimax_error` | | `#region: Tool Configuration` | `set_agent_tools`, `set_tool_preset`, `set_bias_profile`, `get_bias_profile`, `_build_anthropic_tools`, `_get_anthropic_tools`, `_gemini_tool_declaration`, `_build_deepseek_tools`, `_get_deepseek_tools`, `_content_block_to_dict` | | `#region: Tool Execution` | `_execute_tool_calls_concurrently`, `_execute_single_tool_call_async`, `_run_script`, `_truncate_tool_output` | | `#region: File Context Building` | `_reread_file_items`, `_build_file_context_text`, `_build_file_diff_text` | | `#region: Token Estimation` | `_estimate_message_tokens`, `_invalidate_token_estimate`, `_estimate_prompt_tokens`, `_strip_stale_file_refreshes` | | `#region: History Management` | `_trim_anthropic_history`, `_repair_anthropic_history`, `_repair_deepseek_history`, `_add_history_cache_breakpoint`, `_strip_cache_controls` | | `#region: Gemini Provider` | `_ensure_gemini_client`, `_get_gemini_history_list`, `_send_gemini`, `_send_gemini_cli`, `get_gemini_cache_stats` | | `#region: Anthropic Provider` | `_ensure_anthropic_client`, `_chunk_text`, `_build_chunked_context_blocks`, `_send_anthropic` | | `#region: DeepSeek Provider` | `_ensure_deepseek_client`, `_send_deepseek` | | `#region: MiniMax Provider` | `_ensure_minimax_client`, `_send_minimax` | | `#region: Tier 4 Analysis` | `run_tier4_analysis`, `run_tier4_patch_callback`, `run_tier4_patch_generation` | | `#region: Session & Public API` | `reset_session`, `get_token_stats`, `send`, `_add_bleed_derived`, `run_subagent_summarization` | ### 3. Vertical Compaction Apply alignment to error classifier functions: ```python # Before if status == 'running': col = (0.0, 1.0, 0.0, 1.0) elif status == 'starting': col = (1.0, 1.0, 0.0, 1.0) elif status == 'error': col = (1.0, 0.0, 0.0, 1.0) # Apply to _classify_*_error functions with similar patterns ``` ## Non-Functional Requirements - No logic changes — purely organizational - All existing `[C: ...]` SDM tags preserved - All call sites continue to work (50+ references) - 1-space indentation maintained ## Out of Scope - Extraction of class methods to module-level functions - Indentation changes - Logic modifications - Test changes (unless regression detected) ## Architecture Reference - `conductor/code_styleguides/python.md` — Style conventions - `src/gui_2.py` — Reference for region block pattern (5000+ line refactor) - `docs/guide_architecture.md` — AI client threading model context