# 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