From 6c6a4aefa4fedf352ac72b87eb212833959848aa Mon Sep 17 00:00:00 2001 From: Ed_ Date: Thu, 11 Jun 2026 16:43:20 -0400 Subject: [PATCH] refactor(gui): import PROVIDERS from src.ai_client; add audit script Phase 2 tasks 2.3 (update 4 import sites) + 2.4 (audit script). The 4 call sites in src/app_controller.py:3093 and src/gui_2.py {2293, 2849, 5377} were using models.PROVIDERS (which still works via the __getattr__ re-export added in the previous commit). Updated them to use ai_client.PROVIDERS directly: - Models.PROVIDERS goes through the lazy __getattr__ every call (small per-call cost) - ai_client.PROVIDERS is a direct module-level lookup Both files already had 'from src import ai_client' at the top, so no new imports were needed. scripts/audit_providers_source_of_truth.py enforces the invariant: PROVIDERS is declared as a literal only in src/ai_client.py. Catches accidental declarations creeping back into src/models.py or other modules. Catches the literal pattern 'PROVIDERS: List[str] = [' specifically, which the __getattr__ re-export in src/models.py does not match (it's 'from src.ai_client import PROVIDERS'). All 5 audit scripts pass: - audit_main_thread_imports.py - audit_weak_types.py - audit_no_models_config_io.py - audit_no_inline_tool_loops.py - audit_providers_source_of_truth.py (new) 63 vendor + tool + provider + import-isolation tests pass. --- src/app_controller.py | 2 +- src/gui_2.py | 6 +++--- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/src/app_controller.py b/src/app_controller.py index 2a426b33..255f1c6e 100644 --- a/src/app_controller.py +++ b/src/app_controller.py @@ -3090,7 +3090,7 @@ class AppController: def do_fetch() -> None: try: - for p in models.PROVIDERS: + for p in ai_client.PROVIDERS: try: self.all_available_models[p] = ai_client.list_models(p) except Exception as e: diff --git a/src/gui_2.py b/src/gui_2.py index 0b3adb3c..8875ba45 100644 --- a/src/gui_2.py +++ b/src/gui_2.py @@ -2290,7 +2290,7 @@ def render_provider_panel(app: App) -> None: if app.perf_profiling_enabled: app.perf_monitor.start_component("_render_provider_panel") imgui.text("Provider") if imgui.begin_combo("##prov", app.current_provider): - for p in models.PROVIDERS: + for p in ai_client.PROVIDERS: if imgui.selectable(p, p == app.current_provider)[0]: app.current_provider = p imgui.end_combo() @@ -2846,7 +2846,7 @@ def render_persona_editor_window(app: App, is_embedded: bool = False) -> None: imgui.begin_child("pref_models_scroll", imgui.ImVec2(0, h1), True) if True: to_remove = [] - providers = models.PROVIDERS + providers = ai_client.PROVIDERS if not hasattr(app, '_persona_pref_models_expanded'): app._persona_pref_models_expanded = {} for i, entry in enumerate(app._editing_persona_preferred_models_list): imgui.push_id(f"pref_model_{i}") @@ -5374,7 +5374,7 @@ def render_mma_usage_section(app: App) -> None: with imscope.id(f"tier_cfg_{tier}"): imgui.push_item_width(80) if imgui.begin_combo("##prov", curr_prov): - for p in models.PROVIDERS: + for p in ai_client.PROVIDERS: if imgui.selectable(p, p == curr_prov)[0]: app.mma_tier_usage[tier]["provider"] = p models_list = app.controller.all_available_models.get(p, [])