From 0823da93e5f81fa72d07903b899fc70bd2937a6c Mon Sep 17 00:00:00 2001 From: Ed_ Date: Fri, 26 Jun 2026 14:12:37 -0400 Subject: [PATCH] refactor(ai_client): move DEFAULT_TOOL_CATEGORIES from models.py to ai_client.py Per post_module_taxonomy_de_cruft_20260627 Phase 3 (FR6). The DEFAULT_TOOL_CATEGORIES constant groups the canonical MCP tool list for the UI's category filter. The AI client is the natural owner (it owns the tool spec registry via src.mcp_tool_specs); models.py is a data-class shim, not a UI-config registry. This commit: 1. Adds DEFAULT_TOOL_CATEGORIES (the 7-category dict) to src/ai_client.py after the PROVIDERS constant. The dict is identical to the one that was in models.py. 2. Updates src/gui_2.py (the single consumer) to: - Add 'from src.ai_client import DEFAULT_TOOL_CATEGORIES' to the import block - Replace all 6 'models.DEFAULT_TOOL_CATEGORIES' references with the bare 'DEFAULT_TOOL_CATEGORIES' name 3. Removes the DEFAULT_TOOL_CATEGORIES dict from src/models.py (it was already removed as a side effect of the Phase 2.3 __getattr__ removal commit; the file is now 70 lines). The fix was performed by the one-time script scripts/tier2/artifacts/post_module_taxonomy_de_cruft_20260627/fix_gui2_dtc.py which does an in-place re.sub on src/gui_2.py. Verification: - 'from src.ai_client import DEFAULT_TOOL_CATEGORIES' works - 'from src.models import DEFAULT_TOOL_CATEGORIES' raises ImportError (correctly; the constant moved) - All 7 references in src/gui_2.py resolve to the ai_client version - 'from src.models import Metadata' still returns TrackMetadata (the legacy alias is preserved) --- .../fix_gui2_dtc.py | 14 ++++++++++ src/ai_client.py | 27 +++++++++++++++++++ src/gui_2.py | 13 ++++----- 3 files changed, 48 insertions(+), 6 deletions(-) create mode 100644 scripts/tier2/artifacts/post_module_taxonomy_de_cruft_20260627/fix_gui2_dtc.py diff --git a/scripts/tier2/artifacts/post_module_taxonomy_de_cruft_20260627/fix_gui2_dtc.py b/scripts/tier2/artifacts/post_module_taxonomy_de_cruft_20260627/fix_gui2_dtc.py new file mode 100644 index 00000000..e363b5bc --- /dev/null +++ b/scripts/tier2/artifacts/post_module_taxonomy_de_cruft_20260627/fix_gui2_dtc.py @@ -0,0 +1,14 @@ +import re +import sys +from pathlib import Path + +GUI2 = Path("src/gui_2.py") +content = GUI2.read_text(encoding="utf-8") +original = content +new_content = re.sub(r"\bmodels\.DEFAULT_TOOL_CATEGORIES\b", "DEFAULT_TOOL_CATEGORIES", content) +if new_content == original: + print("no changes") + sys.exit(0) +GUI2.write_text(new_content, encoding="utf-8", newline="") +count = len(re.findall(r"\bDEFAULT_TOOL_CATEGORIES\b", new_content)) +print(f"replaced models.DEFAULT_TOOL_CATEGORIES with DEFAULT_TOOL_CATEGORIES ({count} references now in file)") diff --git a/src/ai_client.py b/src/ai_client.py index 338713b2..52bf6139 100644 --- a/src/ai_client.py +++ b/src/ai_client.py @@ -61,6 +61,33 @@ from src.tool_presets import ToolPresetManager PROVIDERS: List[str] = ["gemini", "anthropic", "gemini_cli", "deepseek", "minimax", "qwen", "grok", "llama"] +# DEFAULT_TOOL_CATEGORIES moved from src/models.py in +# post_module_taxonomy_de_cruft_20260627 Phase 3. The categories are the +# canonical grouping of the MCP tool registry for the UI's category +# filter. The AI client is the natural owner (it owns the tool spec +# registry via src.mcp_tool_specs). +DEFAULT_TOOL_CATEGORIES: Dict[str, List[str]] = { + "General": ["read_file", "list_directory", "search_files", "get_tree", "get_file_summary"], + "Surgical": ["get_file_slice", "set_file_slice", "edit_file"], + "Python": [ + "py_get_skeleton", "py_get_code_outline", "py_get_definition", "py_update_definition", + "py_get_signature", "py_set_signature", "py_get_class_summary", + "py_get_var_declaration", "py_set_var_declaration", "py_get_docstring", + "py_find_usages", "py_get_imports", "py_check_syntax", "py_get_hierarchy", + "py_remove_def", "py_add_def", "py_move_def", "py_region_wrap", + ], + "C/C++": [ + "ts_c_get_skeleton", "ts_cpp_get_skeleton", "ts_c_get_code_outline", + "ts_cpp_get_code_outline", "ts_c_get_definition", "ts_cpp_get_definition", + "ts_c_get_signature", "ts_cpp_get_signature", "ts_c_update_definition", + "ts_cpp_update_definition", + ], + "Web": ["web_search", "fetch_url"], + "Runtime": ["run_powershell", "get_ui_performance"], + "Analysis": ["derive_code_path"], + "Beads": ["bd_create", "bd_update", "bd_list", "bd_ready"], +} + # _require_warmed lives # _require_warmed lives in src/module_loader.py to avoid duplicating the # lookup logic across files that need heavy modules. Re-exported here so diff --git a/src/gui_2.py b/src/gui_2.py index 5cb97ff2..392864e6 100644 --- a/src/gui_2.py +++ b/src/gui_2.py @@ -112,6 +112,7 @@ from src import log_registry # from src import log_pruner from src import models from src.models import GenerateRequest, ConfirmRequest +from src.ai_client import DEFAULT_TOOL_CATEGORIES from src import mcp_client from src import markdown_helper from src import synthesis_formatter @@ -2741,7 +2742,7 @@ def render_agent_tools_panel(app: App) -> None: imgui.end_combo() imgui.dummy(imgui.ImVec2(0, 8)) - cat_options = ["All"] + sorted(list(models.DEFAULT_TOOL_CATEGORIES.keys())) + cat_options = ["All"] + sorted(list(DEFAULT_TOOL_CATEGORIES.keys())) #NOTE(Ed): Exception(Thirdparty) try: f_idx = cat_options.index(app.ui_tool_filter_category) @@ -3231,7 +3232,7 @@ def render_tool_preset_manager_content(app: App, is_embedded: bool = False) -> N imgui.begin_child("tp_list_pane", imgui.ImVec2(0, 0), False) if True: if imgui.button("New Preset", imgui.ImVec2(-1, 0)): - app._editing_tool_preset_name = ""; app._editing_tool_preset_categories = {cat: {} for cat in models.DEFAULT_TOOL_CATEGORIES} + app._editing_tool_preset_name = ""; app._editing_tool_preset_categories = {cat: {} for cat in DEFAULT_TOOL_CATEGORIES} app._editing_tool_preset_scope = "project"; app._selected_tool_preset_idx = -1 imgui.separator() preset_names = sorted(app.controller.tool_presets.keys()) @@ -3270,12 +3271,12 @@ def render_tool_preset_manager_content(app: App, is_embedded: bool = False) -> N if opened_t != app._tool_list_open: app._tool_list_open = opened_t if app._tool_list_open: imgui.text("Filter:"); imgui.same_line() - cat_opts = ["All"] + sorted(list(models.DEFAULT_TOOL_CATEGORIES.keys())) + cat_opts = ["All"] + sorted(list(DEFAULT_TOOL_CATEGORIES.keys())) f_idx = cat_opts.index(app.ui_tool_filter_category) if app.ui_tool_filter_category in cat_opts else 0 imgui.set_next_item_width(200); ch_cat, next_f_idx = imgui.combo("##tp_filter", f_idx, cat_opts) if ch_cat: app.ui_tool_filter_category = cat_opts[next_f_idx] with imscope.child("tp_scroll", 0, h1, True): - for cat_name, default_tools in models.DEFAULT_TOOL_CATEGORIES.items(): + for cat_name, default_tools in DEFAULT_TOOL_CATEGORIES.items(): if app.ui_tool_filter_category != "All" and app.ui_tool_filter_category != cat_name: continue if imgui.tree_node(cat_name): if cat_name not in app._editing_tool_preset_categories: app._editing_tool_preset_categories[cat_name] = [] @@ -3344,7 +3345,7 @@ def render_tool_preset_manager_content(app: App, is_embedded: bool = False) -> N if app._bias_weights_open: imgui.begin_child("btool_scroll", imgui.ImVec2(0, bh1), True) if True: - for cat_name, default_tools in models.DEFAULT_TOOL_CATEGORIES.items(): + for cat_name, default_tools in DEFAULT_TOOL_CATEGORIES.items(): if imgui.tree_node(f"{cat_name}##b_list"): if imgui.begin_table(f"bt_{cat_name}", 2): imgui.table_setup_column("T", imgui.TableColumnFlags_.width_fixed, 220) @@ -3371,7 +3372,7 @@ def render_tool_preset_manager_content(app: App, is_embedded: bool = False) -> N if imgui.begin_table("bcats", 2): imgui.table_setup_column("C", imgui.TableColumnFlags_.width_fixed, 220) imgui.table_setup_column("M", imgui.TableColumnFlags_.width_stretch) - for cn in sorted(models.DEFAULT_TOOL_CATEGORIES.keys()): + for cn in sorted(DEFAULT_TOOL_CATEGORIES.keys()): imgui.table_next_row(); imgui.table_next_column() imgui.text(cn); imgui.table_next_column() curr_m = app._editing_bias_profile_category_multipliers.get(cn, 1.0); imgui.set_next_item_width(-1)