Private
Public Access
0
0

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.
This commit is contained in:
2026-06-11 16:43:20 -04:00
parent 74c3b6b274
commit 6c6a4aefa4
2 changed files with 4 additions and 4 deletions
+1 -1
View File
@@ -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:
+3 -3
View File
@@ -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, [])