From ca8e33837b8d505da2598a4c3319724467a130af Mon Sep 17 00:00:00 2001 From: Ed_ Date: Tue, 10 Mar 2026 22:29:43 -0400 Subject: [PATCH] refactor(gui): streamline preset manager and improve tool bias ui --- config.toml | 8 +-- src/app_controller.py | 11 +--- src/gui_2.py | 141 ++++++++++++++++++++++++++++-------------- src/models.py | 15 +---- 4 files changed, 103 insertions(+), 72 deletions(-) diff --git a/config.toml b/config.toml index d0bc609..9c7fa1f 100644 --- a/config.toml +++ b/config.toml @@ -16,7 +16,7 @@ paths = [ "C:\\projects\\manual_slop\\tests\\artifacts\\temp_liveexecutionsim.toml", "C:\\projects\\manual_slop\\tests\\artifacts\\temp_project.toml", ] -active = "C:\\projects\\manual_slop\\tests\\artifacts\\live_gui_workspace\\manual_slop.toml" +active = "C:/projects/gencpp/gencpp_sloppy.toml" [gui] separate_message_panel = false @@ -24,7 +24,7 @@ separate_response_panel = false separate_tool_calls_panel = false bg_shader_enabled = true crt_filter_enabled = false -separate_task_dag = true +separate_task_dag = false separate_usage_analytics = true separate_tier1 = false separate_tier2 = false @@ -36,7 +36,7 @@ separate_tier4 = false "Files & Media" = true "AI Settings" = true "MMA Dashboard" = true -"Task DAG" = true +"Task DAG" = false "Usage Analytics" = false "Tier 1" = false "Tier 2" = false @@ -53,7 +53,7 @@ Response = false "Tool Calls" = false Theme = true "Log Management" = true -Diagnostics = true +Diagnostics = false [theme] palette = "Nord Dark" diff --git a/src/app_controller.py b/src/app_controller.py index b38ac4b..32b6c8f 100644 --- a/src/app_controller.py +++ b/src/app_controller.py @@ -1859,20 +1859,13 @@ class AppController: else: self.ui_project_system_prompt = preset.system_prompt self.ui_project_preset_name = name - if preset.temperature is not None: - self.temperature = preset.temperature - if preset.max_output_tokens is not None: - self.max_tokens = preset.max_output_tokens - def _cb_save_preset(self, name, content, temp, top_p, max_tok, scope): + def _cb_save_preset(self, name, content, scope): if not name or not name.strip(): raise ValueError("Preset name cannot be empty or whitespace.") preset = models.Preset( name=name, - system_prompt=content, - temperature=temp, - top_p=top_p, - max_output_tokens=max_tok + system_prompt=content ) self.preset_manager.save_preset(preset, scope) self.presets = self.preset_manager.load_all() diff --git a/src/gui_2.py b/src/gui_2.py index 5ca58df..af34abf 100644 --- a/src/gui_2.py +++ b/src/gui_2.py @@ -117,17 +117,16 @@ class App: self._persona_editor_opened = False self._personas_list: dict[str, dict] = {} self._editing_bias_profile_name = "" - self._editing_bias_profile_tool_weights = "" # JSON - self._editing_bias_profile_cat_mults = "" # JSON + self._editing_bias_profile_tool_weights: dict[str, int] = {} + self._editing_bias_profile_category_multipliers: dict[str, float] = {} self._editing_bias_profile_scope = "project" self._editing_tool_preset_name = '' self._editing_tool_preset_categories = {} self._editing_tool_preset_scope = 'project' self._selected_tool_preset_idx = -1 - self._editing_bias_profile_name = "" - self._editing_bias_profile_tool_weights = "{}" - self._editing_bias_profile_category_multipliers = "{}" self._selected_bias_profile_idx = -1 + self._new_bias_tool_name = "run_powershell" + self._new_bias_category_name = "General" self._editing_preset_name = "" self._editing_preset_content = "" self._editing_preset_temperature = 0.0 @@ -937,9 +936,6 @@ class App: if imgui.button("New Preset", imgui.ImVec2(-1, 0)): self._editing_preset_name = "" self._editing_preset_content = "" - self._editing_preset_temperature = 0.0 - self._editing_preset_top_p = 1.0 - self._editing_preset_max_output_tokens = 4096 self._editing_preset_scope = "project" self._editing_preset_is_new = True imgui.separator() @@ -949,9 +945,6 @@ class App: if imgui.selectable(name, is_sel)[0]: self._editing_preset_name = name self._editing_preset_content = p.system_prompt - self._editing_preset_temperature = p.temperature if p.temperature is not None else 0.0 - self._editing_preset_top_p = p.top_p if p.top_p is not None else 1.0 - self._editing_preset_max_output_tokens = p.max_output_tokens if p.max_output_tokens is not None else 4096 self._editing_preset_is_new = False finally: imgui.end_child() @@ -970,23 +963,13 @@ class App: if imgui.radio_button("Project", self._editing_preset_scope == "project"): self._editing_preset_scope = "project" imgui.text("Content:") - _, self._editing_preset_content = imgui.input_text_multiline("##edit_content", self._editing_preset_content, imgui.ImVec2(-1, 280)) - - imgui.text("Temperature:") - _, self._editing_preset_temperature = imgui.input_float("##edit_temp", self._editing_preset_temperature, 0.1, 1.0, "%.2f") - imgui.text("Top P:") - _, self._editing_preset_top_p = imgui.input_float("##edit_top_p", self._editing_preset_top_p, 0.1, 1.0, "%.2f") - imgui.text("Max Output Tokens:") - _, self._editing_preset_max_output_tokens = imgui.input_int("##edit_max_tokens", self._editing_preset_max_output_tokens) + _, self._editing_preset_content = imgui.input_text_multiline("##edit_content", self._editing_preset_content, imgui.ImVec2(-1, -40)) if imgui.button("Save", imgui.ImVec2(120, 0)): if self._editing_preset_name.strip(): self.controller._cb_save_preset( self._editing_preset_name.strip(), self._editing_preset_content, - self._editing_preset_temperature, - self._editing_preset_top_p, - self._editing_preset_max_output_tokens, self._editing_preset_scope ) self.ai_status = f"Preset '{self._editing_preset_name.strip()}' saved to {self._editing_preset_scope}" @@ -1115,14 +1098,14 @@ class App: imgui.separator() imgui.text_colored(C_SUB, "Bias Profiles") - imgui.begin_child("bias_profiles_area", imgui.ImVec2(0, 200), True) + imgui.begin_child("bias_profiles_area", imgui.ImVec2(0, 300), True) try: avail_bias = imgui.get_content_region_avail() imgui.begin_child("bias_list", imgui.ImVec2(200, avail_bias.y), False) if imgui.button("New Profile", imgui.ImVec2(-1, 0)): self._editing_bias_profile_name = "" - self._editing_bias_profile_tool_weights = "{}" - self._editing_bias_profile_category_multipliers = "{}" + self._editing_bias_profile_tool_weights = {} + self._editing_bias_profile_category_multipliers = {} self._selected_bias_profile_idx = -1 imgui.separator() bnames = sorted(self.bias_profiles.keys()) @@ -1132,23 +1115,74 @@ class App: self._selected_bias_profile_idx = i self._editing_bias_profile_name = bname profile = self.bias_profiles[bname] - self._editing_bias_profile_tool_weights = json.dumps(profile.tool_weights, indent=1) - self._editing_bias_profile_category_multipliers = json.dumps(profile.category_multipliers, indent=1) + self._editing_bias_profile_tool_weights = copy.deepcopy(profile.tool_weights) + self._editing_bias_profile_category_multipliers = copy.deepcopy(profile.category_multipliers) imgui.end_child() imgui.same_line() imgui.begin_child("bias_edit", imgui.ImVec2(0, avail_bias.y), False) imgui.text("Name:") _, self._editing_bias_profile_name = imgui.input_text("##b_name", self._editing_bias_profile_name) - imgui.text("Tool Weights (JSON):") - _, self._editing_bias_profile_tool_weights = imgui.input_text_multiline("##b_tw", self._editing_bias_profile_tool_weights, imgui.ImVec2(-1, 60)) - imgui.text("Category Multipliers (JSON):") - _, self._editing_bias_profile_category_multipliers = imgui.input_text_multiline("##b_cm", self._editing_bias_profile_category_multipliers, imgui.ImVec2(-1, 60)) + imgui.text_colored(C_KEY, "Tool Weights:") + to_remove_tw = [] + for tw_name, tw_val in list(self._editing_bias_profile_tool_weights.items()): + imgui.text(f" {tw_name}:") + imgui.same_line(150) + imgui.set_next_item_width(100) + changed, new_val = imgui.slider_int(f"##tw_{tw_name}", tw_val, 1, 10) + if changed: self._editing_bias_profile_tool_weights[tw_name] = new_val + imgui.same_line() + if imgui.button(f"x##rem_tw_{tw_name}"): + to_remove_tw.append(tw_name) + for r in to_remove_tw: del self._editing_bias_profile_tool_weights[r] + + # Add Tool Override + imgui.set_next_item_width(150) + if imgui.begin_combo("##add_tw_combo", self._new_bias_tool_name): + for tn in models.AGENT_TOOL_NAMES: + if tn not in self._editing_bias_profile_tool_weights: + if imgui.selectable(tn, tn == self._new_bias_tool_name)[0]: + self._new_bias_tool_name = tn + imgui.end_combo() + imgui.same_line() + if imgui.button("Add Tool Override"): + self._editing_bias_profile_tool_weights[self._new_bias_tool_name] = 5 + + imgui.dummy(imgui.ImVec2(0, 4)) + imgui.text_colored(C_KEY, "Category Multipliers:") + to_remove_cm = [] + for cm_name, cm_val in list(self._editing_bias_profile_category_multipliers.items()): + imgui.text(f" {cm_name}:") + imgui.same_line(150) + imgui.set_next_item_width(100) + changed, new_val = imgui.slider_float(f"##cm_{cm_name}", cm_val, 0.1, 5.0, "%.1fx") + if changed: self._editing_bias_profile_category_multipliers[cm_name] = new_val + imgui.same_line() + if imgui.button(f"x##rem_cm_{cm_name}"): + to_remove_cm.append(cm_name) + for r in to_remove_cm: del self._editing_bias_profile_category_multipliers[r] + + # Add Category Override + imgui.set_next_item_width(150) + cat_names = sorted(list(models.DEFAULT_TOOL_CATEGORIES.keys())) + if imgui.begin_combo("##add_cm_combo", self._new_bias_category_name): + for cn in cat_names: + if cn not in self._editing_bias_profile_category_multipliers: + if imgui.selectable(cn, cn == self._new_bias_category_name)[0]: + self._new_bias_category_name = cn + imgui.end_combo() + imgui.same_line() + if imgui.button("Add Category Override"): + self._editing_bias_profile_category_multipliers[self._new_bias_category_name] = 1.0 + + imgui.dummy(imgui.ImVec2(0, 8)) if imgui.button("Save Profile"): try: - tw = json.loads(self._editing_bias_profile_tool_weights) - cm = json.loads(self._editing_bias_profile_category_multipliers) - prof = models.BiasProfile(name=self._editing_bias_profile_name, tool_weights=tw, category_multipliers=cm) + prof = models.BiasProfile( + name=self._editing_bias_profile_name, + tool_weights=self._editing_bias_profile_tool_weights, + category_multipliers=self._editing_bias_profile_category_multipliers + ) self.controller._cb_save_bias_profile(prof, self._editing_tool_preset_scope) self.ai_status = f"Bias profile '{prof.name}' saved" except Exception as e: @@ -1209,14 +1243,16 @@ class App: imgui.pop_item_width() imgui.text("Provider:") imgui.same_line() - providers = ["gemini", "anthropic", "deepseek"] + providers = self.controller.PROVIDERS p_idx = providers.index(self._editing_persona_provider) + 1 if self._editing_persona_provider in providers else 0 imgui.push_item_width(120) _, p_idx = imgui.combo("##pprov", p_idx, ["None"] + providers) self._editing_persona_provider = providers[p_idx - 1] if p_idx > 0 else "" imgui.pop_item_width() imgui.text("Model:") - all_models = ["gemini-2.5-flash", "gemini-3.1-pro-preview", "claude-3-5-sonnet", "deepseek-v3"] + all_models = self.controller.all_available_models.get(self._editing_persona_provider, []) + if not all_models and self._editing_persona_model: + all_models = [self._editing_persona_model] m_idx = all_models.index(self._editing_persona_model) + 1 if self._editing_persona_model in all_models else 0 imgui.push_item_width(150) _, m_idx = imgui.combo("##pmodel", m_idx, ["None"] + all_models) @@ -1238,6 +1274,9 @@ class App: _, t_idx = imgui.combo("##ptoolpreset", t_idx, preset_names) self._editing_persona_tool_preset_id = preset_names[t_idx] if t_idx > 0 else None imgui.pop_item_width() + imgui.same_line() + if imgui.button("Manage Tools##pm"): + self.show_tool_preset_manager_modal = True # Bias Profile imgui.text("Bias Profile:") @@ -1249,22 +1288,34 @@ class App: self._editing_persona_bias_profile_id = bias_names[b_idx] if b_idx > 0 else None imgui.pop_item_width() - imgui.text("Pref Models (JSON):") + imgui.text("Pref Models (comma-separated):") _, self._editing_persona_preferred_models = imgui.input_text("##pprefmodels", self._editing_persona_preferred_models, 256) + imgui.text("Load Prompt Preset:") + imgui.same_line() + prompt_presets = ["None"] + sorted(self.controller.presets.keys()) + imgui.push_item_width(150) + changed_pr, pr_idx = imgui.combo("##load_prompt_preset", 0, prompt_presets) + imgui.pop_item_width() + if changed_pr and pr_idx > 0: + pname = prompt_presets[pr_idx] + if pname in self.controller.presets: + p = self.controller.presets[pname] + self._editing_persona_system_prompt = p.system_prompt + if p.temperature is not None: self._editing_persona_temperature = p.temperature + if p.max_output_tokens is not None: self._editing_persona_max_tokens = p.max_output_tokens + imgui.same_line() + if imgui.button("Manage Prompts##pm"): + self.show_preset_manager_modal = True + imgui.text("Prompt:") _, self._editing_persona_system_prompt = imgui.input_text_multiline("##pprompt", self._editing_persona_system_prompt, imgui.ImVec2(350, 50)) if imgui.button("Save##p", imgui.ImVec2(80, 0)): if self._editing_persona_name.strip(): try: - import json - pref_models = [] - try: - pref_models = json.loads(self._editing_persona_preferred_models) - if not isinstance(pref_models, list): - pref_models = [] - except: - pass + pref_models = [m.strip() for m in self._editing_persona_preferred_models.split(",") if m.strip()] + if self._editing_persona_preferred_models.strip() == "[]": + pref_models = [] persona = models.Persona( name=self._editing_persona_name.strip(), provider=self._editing_persona_provider or None, diff --git a/src/models.py b/src/models.py index 2439fe6..460ef0b 100644 --- a/src/models.py +++ b/src/models.py @@ -349,30 +349,17 @@ class FileItem: class Preset: name: str system_prompt: str - temperature: Optional[float] = None - top_p: Optional[float] = None - max_output_tokens: Optional[int] = None def to_dict(self) -> Dict[str, Any]: - res = { + return { "system_prompt": self.system_prompt, } - if self.temperature is not None: - res["temperature"] = self.temperature - if self.top_p is not None: - res["top_p"] = self.top_p - if self.max_output_tokens is not None: - res["max_output_tokens"] = self.max_output_tokens - return res @classmethod def from_dict(cls, name: str, data: Dict[str, Any]) -> "Preset": return cls( name=name, system_prompt=data.get("system_prompt", ""), - temperature=data.get("temperature"), - top_p=data.get("top_p"), - max_output_tokens=data.get("max_output_tokens"), ) @dataclass