diff --git a/config.toml b/config.toml index 9c7fa1f..bae3b4d 100644 --- a/config.toml +++ b/config.toml @@ -1,11 +1,11 @@ [ai] -provider = "gemini_cli" -model = "gemini-2.5-flash-lite" -temperature = 0.30000001192092896 +provider = "minimax" +model = "MiniMax-M2.5" +temperature = 0.0 max_tokens = 32000 history_trunc_limit = 900000 -active_preset = "TestGlobal" -system_prompt = "Overridden Prompt" +active_preset = "Default" +system_prompt = "" [projects] paths = [ @@ -25,10 +25,10 @@ separate_tool_calls_panel = false bg_shader_enabled = true crt_filter_enabled = false separate_task_dag = false -separate_usage_analytics = true +separate_usage_analytics = false separate_tier1 = false separate_tier2 = false -separate_tier3 = true +separate_tier3 = false separate_tier4 = false [gui.show_windows] @@ -44,7 +44,7 @@ separate_tier4 = false "Tier 4" = false "Tier 1: Strategy" = false "Tier 2: Tech Lead" = false -"Tier 3: Workers" = true +"Tier 3: Workers" = false "Tier 4: QA" = false "Discussion Hub" = true "Operations Hub" = true @@ -59,9 +59,9 @@ Diagnostics = false palette = "Nord Dark" font_path = "C:/projects/manual_slop/assets/fonts/Inter-Regular.ttf" font_size = 14.0 -scale = 1.0 -transparency = 0.5099999904632568 -child_transparency = 0.699999988079071 +scale = 1.0099999904632568 +transparency = 1.0 +child_transparency = 1.0 [mma] max_workers = 4 diff --git a/manualslop_layout.ini b/manualslop_layout.ini index 8d1cdd4..09755d0 100644 --- a/manualslop_layout.ini +++ b/manualslop_layout.ini @@ -73,8 +73,8 @@ Collapsed=0 DockId=0xAFC85805,2 [Window][Theme] -Pos=0,1016 -Size=623,401 +Pos=0,1670 +Size=840,467 Collapsed=0 DockId=0x00000002,2 @@ -84,14 +84,14 @@ Size=900,700 Collapsed=0 [Window][Diagnostics] -Pos=2833,28 -Size=1007,2109 +Pos=2641,22 +Size=1199,2115 Collapsed=0 DockId=0x0000000C,2 [Window][Context Hub] -Pos=0,1016 -Size=623,401 +Pos=0,1670 +Size=840,467 Collapsed=0 DockId=0x00000002,1 @@ -102,26 +102,26 @@ Collapsed=0 DockId=0x0000000D,0 [Window][Discussion Hub] -Pos=1296,22 -Size=659,1395 +Pos=1668,22 +Size=971,2115 Collapsed=0 DockId=0x00000013,0 [Window][Operations Hub] -Pos=625,22 -Size=669,1395 +Pos=842,22 +Size=824,2115 Collapsed=0 DockId=0x00000012,0 [Window][Files & Media] -Pos=0,1016 -Size=623,401 +Pos=0,1670 +Size=840,467 Collapsed=0 DockId=0x00000002,0 [Window][AI Settings] Pos=0,22 -Size=623,992 +Size=840,1646 Collapsed=0 DockId=0x00000001,0 @@ -131,14 +131,14 @@ Size=416,325 Collapsed=0 [Window][MMA Dashboard] -Pos=1957,22 -Size=603,1395 +Pos=2641,22 +Size=1199,2115 Collapsed=0 DockId=0x0000000C,0 [Window][Log Management] -Pos=1957,22 -Size=603,1395 +Pos=2641,22 +Size=1199,2115 Collapsed=0 DockId=0x0000000C,1 @@ -166,8 +166,8 @@ Collapsed=0 DockId=0x0000000F,0 [Window][Tier 3: Workers] -Pos=2905,1238 -Size=935,899 +Pos=2641,1235 +Size=1199,902 Collapsed=0 DockId=0x0000000F,0 @@ -322,12 +322,12 @@ Size=420,966 Collapsed=0 [Window][Preset Manager] -Pos=403,396 -Size=956,958 +Pos=1693,826 +Size=933,839 Collapsed=0 [Window][Task DAG] -Pos=1700,1199 +Pos=1661,1181 Size=1079,662 Collapsed=0 @@ -337,13 +337,13 @@ Size=275,375 Collapsed=0 [Window][Tool Preset Manager] -Pos=192,90 -Size=1066,1324 +Pos=1014,522 +Size=1155,1011 Collapsed=0 [Window][Persona Editor] -Pos=956,447 -Size=549,447 +Pos=995,597 +Size=1868,1434 Collapsed=0 [Table][0xFB6E3870,4] @@ -377,11 +377,11 @@ Column 3 Width=20 Column 4 Weight=1.0000 [Table][0x2A6000B6,4] -RefScale=17 -Column 0 Width=51 -Column 1 Width=76 +RefScale=14 +Column 0 Width=42 +Column 1 Width=62 Column 2 Weight=1.0000 -Column 3 Width=128 +Column 3 Width=105 [Table][0x8BCC69C7,6] RefScale=13 @@ -393,18 +393,18 @@ Column 4 Weight=1.0000 Column 5 Width=50 [Table][0x3751446B,4] -RefScale=20 -Column 0 Width=60 -Column 1 Width=91 +RefScale=17 +Column 0 Width=51 +Column 1 Width=77 Column 2 Weight=1.0000 -Column 3 Width=151 +Column 3 Width=128 [Table][0x2C515046,4] -RefScale=20 -Column 0 Width=63 +RefScale=14 +Column 0 Width=43 Column 1 Weight=1.0000 -Column 2 Width=152 -Column 3 Width=60 +Column 2 Width=106 +Column 3 Width=42 [Table][0xD99F45C5,4] Column 0 Sort=0v @@ -425,28 +425,28 @@ Column 1 Width=100 Column 2 Weight=1.0000 [Table][0xA02D8C87,3] -RefScale=20 -Column 0 Width=227 -Column 1 Width=150 +RefScale=14 +Column 0 Width=158 +Column 1 Width=105 Column 2 Weight=1.0000 [Docking][Data] DockNode ID=0x00000008 Pos=3125,170 Size=593,1157 Split=Y DockNode ID=0x00000009 Parent=0x00000008 SizeRef=1029,147 Selected=0x0469CA7A DockNode ID=0x0000000A Parent=0x00000008 SizeRef=1029,145 Selected=0xDF822E02 -DockSpace ID=0xAFC85805 Window=0x079D3A04 Pos=0,22 Size=2560,1395 Split=X - DockNode ID=0x00000003 Parent=0xAFC85805 SizeRef=1955,1183 Split=X +DockSpace ID=0xAFC85805 Window=0x079D3A04 Pos=0,22 Size=3840,2115 Split=X + DockNode ID=0x00000003 Parent=0xAFC85805 SizeRef=2639,1183 Split=X DockNode ID=0x0000000B Parent=0x00000003 SizeRef=404,1186 Split=X Selected=0xF4139CA2 - DockNode ID=0x00000007 Parent=0x0000000B SizeRef=623,858 Split=Y Selected=0x8CA2375C - DockNode ID=0x00000001 Parent=0x00000007 SizeRef=824,989 CentralNode=1 Selected=0x7BD57D6A - DockNode ID=0x00000002 Parent=0x00000007 SizeRef=824,401 Selected=0x1DCB2623 - DockNode ID=0x0000000E Parent=0x0000000B SizeRef=1330,858 Split=X Selected=0x418C7449 - DockNode ID=0x00000012 Parent=0x0000000E SizeRef=669,402 Selected=0x418C7449 - DockNode ID=0x00000013 Parent=0x0000000E SizeRef=659,402 Selected=0x6F2B5B04 + DockNode ID=0x00000007 Parent=0x0000000B SizeRef=840,858 Split=Y Selected=0x8CA2375C + DockNode ID=0x00000001 Parent=0x00000007 SizeRef=824,1646 CentralNode=1 Selected=0x7BD57D6A + DockNode ID=0x00000002 Parent=0x00000007 SizeRef=824,467 Selected=0x1DCB2623 + DockNode ID=0x0000000E Parent=0x0000000B SizeRef=1797,858 Split=X Selected=0x418C7449 + DockNode ID=0x00000012 Parent=0x0000000E SizeRef=824,402 Selected=0x418C7449 + DockNode ID=0x00000013 Parent=0x0000000E SizeRef=971,402 Selected=0x6F2B5B04 DockNode ID=0x0000000D Parent=0x00000003 SizeRef=435,1186 Selected=0x363E93D6 - DockNode ID=0x00000004 Parent=0xAFC85805 SizeRef=603,1183 Split=Y Selected=0x3AEC3498 - DockNode ID=0x0000000C Parent=0x00000004 SizeRef=1074,1208 Selected=0x2C0206CE - DockNode ID=0x0000000F Parent=0x00000004 SizeRef=1074,899 Selected=0x5CDB7A4B + DockNode ID=0x00000004 Parent=0xAFC85805 SizeRef=1199,1183 Split=Y Selected=0x3AEC3498 + DockNode ID=0x0000000C Parent=0x00000004 SizeRef=1074,1208 Selected=0x3AEC3498 + DockNode ID=0x0000000F Parent=0x00000004 SizeRef=1074,899 Selected=0x655BC6E9 ;;;<<>>;;; ;;;<<>>;;; diff --git a/personas.toml b/personas.toml index 454c763..a8b87d3 100644 --- a/personas.toml +++ b/personas.toml @@ -1,10 +1,19 @@ [personas.Default] system_prompt = "" -provider = "minimax" +tool_preset = "Default" +bias_profile = "Balanced" + +[[personas.Default.preferred_models]] model = "MiniMax-M2.5" -preferred_models = [ - "MiniMax-M2.5", -] +provider = "minimax" temperature = 0.0 top_p = 1.0 max_output_tokens = 32000 +history_trunc_limit = 900000 + +[[personas.Default.preferred_models]] +provider = "gemini_cli" +model = "gemini-3-flash-preview" +temperature = -1.4901161193847656e-08 +max_output_tokens = 32000 +history_trunc_limit = 900000 diff --git a/scripts/migrate_personas.py b/scripts/migrate_personas.py index a30de89..9ba8a03 100644 --- a/scripts/migrate_personas.py +++ b/scripts/migrate_personas.py @@ -34,13 +34,8 @@ def migrate(): preset = models.Preset.from_dict(name, data) persona = models.Persona( name=name, - provider=provider, - model=model, - preferred_models=[model] if model else [], - system_prompt=preset.system_prompt, - temperature=preset.temperature, - top_p=preset.top_p, - max_output_tokens=preset.max_output_tokens + preferred_models=[{"provider": provider, "model": model}], + system_prompt=preset.system_prompt ) persona_manager.save_persona(persona, scope="global") print(f"Migrated global preset to persona: {name}") @@ -50,12 +45,13 @@ def migrate(): if active_preset and active_preset not in persona_manager.load_all(): persona = models.Persona( name=active_preset, - provider=provider, - model=model, - preferred_models=[model] if model else [], - system_prompt=ai_cfg.get("system_prompt", ""), - temperature=ai_cfg.get("temperature"), - max_output_tokens=ai_cfg.get("max_tokens") + preferred_models=[{ + "provider": provider, + "model": model, + "temperature": ai_cfg.get("temperature"), + "max_output_tokens": ai_cfg.get("max_tokens") + }], + system_prompt=ai_cfg.get("system_prompt", "") ) persona_manager.save_persona(persona, scope="global") print(f"Created Initial Legacy persona from active_preset: {active_preset}") diff --git a/scripts/refactor_ai_settings_2.py b/scripts/refactor_ai_settings_2.py new file mode 100644 index 0000000..9b37c32 --- /dev/null +++ b/scripts/refactor_ai_settings_2.py @@ -0,0 +1,252 @@ +import sys + +with open("src/gui_2.py", "r", encoding="utf-8") as f: + content = f.read() + +# 1. In _render_provider_panel, remove Fetch Models +old_fetch = """ imgui.text("Model") + imgui.same_line() + if imgui.button("Fetch Models"): + self._fetch_models(self.current_provider) + if imgui.begin_list_box("##models", imgui.ImVec2(-1, 120)):""" +new_fetch = """ imgui.text("Model") + if imgui.begin_list_box("##models", imgui.ImVec2(-1, 120)):""" +content = content.replace(old_fetch, new_fetch) + +# 2. Extract Persona block +# We need to find the start of 'imgui.text("Persona")' and end of 'self._editing_persona_is_new = True' +# Let's be very careful. +old_persona_block = """ imgui.text("Persona") + if not hasattr(self, 'ui_active_persona'): + self.ui_active_persona = "" + personas = getattr(self.controller, 'personas', {}) + if imgui.begin_combo("##persona", self.ui_active_persona or "None"): + if imgui.selectable("None", not self.ui_active_persona)[0]: + self.ui_active_persona = "" + for pname in sorted(personas.keys()): + if imgui.selectable(pname, pname == self.ui_active_persona)[0]: + self.ui_active_persona = pname + if pname in personas: + persona = personas[pname] + self._editing_persona_name = persona.name + self._editing_persona_provider = persona.provider or "" + self._editing_persona_model = persona.model or "" + self._editing_persona_system_prompt = persona.system_prompt or "" + self._editing_persona_temperature = persona.temperature or 0.7 + self._editing_persona_max_tokens = persona.max_output_tokens or 4096 + self._editing_persona_tool_preset_id = persona.tool_preset or "" + self._editing_persona_bias_profile_id = persona.bias_profile or "" + import json + self._editing_persona_preferred_models = json.dumps(persona.preferred_models) if persona.preferred_models else "[]" + self._editing_persona_is_new = False + if persona.provider and persona.provider in self.controller.PROVIDERS: + self.current_provider = persona.provider + if persona.model: + self.current_model = persona.model + if persona.temperature is not None: + ai_client.temperature = persona.temperature + if persona.max_output_tokens: + ai_client.max_output_tokens = persona.max_output_tokens + if persona.system_prompt: + ai_client.system_instruction = persona.system_prompt + if persona.tool_preset: + self.ui_active_tool_preset = persona.tool_preset + ai_client.set_tool_preset(persona.tool_preset) + if persona.bias_profile: + self.ui_active_bias_profile = persona.bias_profile + ai_client.set_bias_profile(persona.bias_profile) + imgui.end_combo() + imgui.same_line() + if imgui.button("Manage Personas"): + self.show_persona_editor_window = True + if self.ui_active_persona and self.ui_active_persona in personas: + persona = personas[self.ui_active_persona] + self._editing_persona_name = persona.name + self._editing_persona_provider = persona.provider or "" + self._editing_persona_model = persona.model or "" + self._editing_persona_system_prompt = persona.system_prompt or "" + self._editing_persona_temperature = persona.temperature if persona.temperature is not None else 0.7 + self._editing_persona_max_tokens = persona.max_output_tokens if persona.max_output_tokens is not None else 4096 + self._editing_persona_tool_preset_id = persona.tool_preset or "" + self._editing_persona_bias_profile_id = persona.bias_profile or "" + self._editing_persona_preferred_models_list = list(persona.preferred_models) if persona.preferred_models else [] + self._editing_persona_scope = self.controller.persona_manager.get_persona_scope(persona.name) + self._editing_persona_is_new = False + else: + self._editing_persona_name = "" + self._editing_persona_provider = self.current_provider + self._editing_persona_model = self.current_model + self._editing_persona_system_prompt = "" + self._editing_persona_temperature = 0.7 + self._editing_persona_max_tokens = 4096 + self._editing_persona_tool_preset_id = "" + self._editing_persona_bias_profile_id = "" + self._editing_persona_preferred_models_list = [] + self._editing_persona_scope = "project" + self._editing_persona_is_new = True""" + +# We need to extract the bias profile block as well +old_bias_block = """ imgui.text("Bias Profile") + if imgui.begin_combo("##bias", self.ui_active_bias_profile or "None"): + if imgui.selectable("None", not self.ui_active_bias_profile)[0]: + self.ui_active_bias_profile = "" + ai_client.set_bias_profile(None) + for bname in sorted(self.bias_profiles.keys()): + if imgui.selectable(bname, bname == self.ui_active_bias_profile)[0]: + self.ui_active_bias_profile = bname + ai_client.set_bias_profile(bname) + imgui.end_combo()""" + +# Remove them from their original spots +content = content.replace(old_bias_block, "") +content = content.replace(old_persona_block, "") + +# Insert Persona block at the top of _render_provider_panel +old_provider_start = """ def _render_provider_panel(self) -> None: + if self.perf_profiling_enabled: self.perf_monitor.start_component("_render_provider_panel") + imgui.text("Provider")""" +new_provider_start = f""" def _render_provider_panel(self) -> None: + if self.perf_profiling_enabled: self.perf_monitor.start_component("_render_provider_panel") +{old_persona_block} + imgui.separator() + imgui.text("Provider")""" +content = content.replace(old_provider_start, new_provider_start) + +# Update _render_agent_tools_panel +old_agent_tools_start = """ def _render_agent_tools_panel(self) -> None: + imgui.text_colored(C_LBL, 'Active Tool Preset')""" +new_agent_tools_start = f""" def _render_agent_tools_panel(self) -> None: + if imgui.collapsing_header("Active Tool Presets & Biases", imgui.TreeNodeFlags_.default_open): + imgui.text("Tool Preset")""" +content = content.replace(old_agent_tools_start, new_agent_tools_start) + +# Wait, if I do collapsing header, I need to indent the rest of the function. +# Instead of indenting the whole function, I can just use the header. +# But wait, ImGui collapsing_header doesn't require indenting, it just returns true if open. +# So I should write it properly: +old_agent_tools_func = """ def _render_agent_tools_panel(self) -> None: + imgui.text_colored(C_LBL, 'Active Tool Preset') + presets = self.controller.tool_presets + preset_names = [""] + sorted(list(presets.keys())) + + # Gracefully handle None or missing preset + active = getattr(self, "ui_active_tool_preset", "") + if active is None: active = "" + try: + idx = preset_names.index(active) + except ValueError: + idx = 0 + + ch, new_idx = imgui.combo("##tool_preset_select", idx, preset_names) + if ch: + self.ui_active_tool_preset = preset_names[new_idx] + + imgui.same_line() + if imgui.button("Manage Presets##tools"): + self.show_tool_preset_manager_window = True + if imgui.is_item_hovered(): + imgui.set_tooltip("Configure tool availability and default modes.") + + imgui.dummy(imgui.ImVec2(0, 8)) + active_name = self.ui_active_tool_preset + if active_name and active_name in presets: + preset = presets[active_name] + for cat_name, tools in preset.categories.items(): + if imgui.tree_node(cat_name): + for tool in tools: + if tool.weight >= 5: + imgui.text_colored(vec4(255, 100, 100), "[HIGH]") + imgui.same_line() + elif tool.weight == 4: + imgui.text_colored(vec4(255, 255, 100), "[PREF]") + imgui.same_line() + elif tool.weight == 2: + imgui.text_colored(vec4(255, 150, 50), "[REJECT]") + imgui.same_line() + elif tool.weight <= 1: + imgui.text_colored(vec4(180, 180, 180), "[LOW]") + imgui.same_line() + + imgui.text(tool.name) + imgui.same_line(180) + + mode = tool.approval + if imgui.radio_button(f"Auto##{cat_name}_{tool.name}", mode == "auto"): + tool.approval = "auto" + imgui.same_line() + if imgui.radio_button(f"Ask##{cat_name}_{tool.name}", mode == "ask"): + tool.approval = "ask" + imgui.tree_pop()""" + +new_agent_tools_func = """ def _render_agent_tools_panel(self) -> None: + if imgui.collapsing_header("Active Tool Presets & Biases", imgui.TreeNodeFlags_.default_open): + imgui.text("Tool Preset") + presets = self.controller.tool_presets + preset_names = [""] + sorted(list(presets.keys())) + + # Gracefully handle None or missing preset + active = getattr(self, "ui_active_tool_preset", "") + if active is None: active = "" + try: + idx = preset_names.index(active) + except ValueError: + idx = 0 + + ch, new_idx = imgui.combo("##tool_preset_select", idx, preset_names) + if ch: + self.ui_active_tool_preset = preset_names[new_idx] + + imgui.same_line() + if imgui.button("Manage Tools##tools"): + self.show_tool_preset_manager_window = True + if imgui.is_item_hovered(): + imgui.set_tooltip("Configure tool availability and default modes.") + + imgui.dummy(imgui.ImVec2(0, 4)) +""" + "\n ".join(old_bias_block.split("\n")) + """ + + imgui.dummy(imgui.ImVec2(0, 8)) + active_name = self.ui_active_tool_preset + if active_name and active_name in presets: + preset = presets[active_name] + for cat_name, tools in preset.categories.items(): + if imgui.tree_node(cat_name): + for tool in tools: + if tool.weight >= 5: + imgui.text_colored(vec4(255, 100, 100), "[HIGH]") + imgui.same_line() + elif tool.weight == 4: + imgui.text_colored(vec4(255, 255, 100), "[PREF]") + imgui.same_line() + elif tool.weight == 2: + imgui.text_colored(vec4(255, 150, 50), "[REJECT]") + imgui.same_line() + elif tool.weight <= 1: + imgui.text_colored(vec4(180, 180, 180), "[LOW]") + imgui.same_line() + + imgui.text(tool.name) + imgui.same_line(180) + + mode = tool.approval + if imgui.radio_button(f"Auto##{cat_name}_{tool.name}", mode == "auto"): + tool.approval = "auto" + imgui.same_line() + if imgui.radio_button(f"Ask##{cat_name}_{tool.name}", mode == "ask"): + tool.approval = "ask" + imgui.tree_pop()""" +content = content.replace(old_agent_tools_func, new_agent_tools_func) + +# Fix cache text display in Usage Analytics +content = content.replace('self._gemini_cache_text = f"Gemini Caches: {count} ({size_bytes / 1024:.1f} KB)"', 'self._gemini_cache_text = f"Cache Usage: {count} ({size_bytes / 1024:.1f} KB)"') +content = content.replace('imgui.text_colored(C_LBL, f"Gemini Cache: ACTIVE | Age: {age:.0f}s / {ttl}s | Renews at: {ttl * 0.9:.0f}s")', 'imgui.text_colored(C_LBL, f"Cache Usage: ACTIVE | Age: {age:.0f}s / {ttl}s | Renews at: {ttl * 0.9:.0f}s")') +content = content.replace('imgui.text_disabled("Gemini Cache: INACTIVE")', 'imgui.text_disabled("Cache Usage: INACTIVE")') + +# Also, user requested: "The persona should problably just mess with the project system prompt for now." +# Currently in persona selection: `ai_client.system_instruction = persona.system_prompt` +# Let's change that to `self.ui_project_system_prompt = persona.system_prompt` and remove ai_client direct injection +content = content.replace('ai_client.system_instruction = persona.system_prompt', 'self.ui_project_system_prompt = persona.system_prompt') + +with open("src/gui_2.py", "w", encoding="utf-8") as f: + f.write(content) +print("done") diff --git a/scripts/refactor_ai_settings_3.py b/scripts/refactor_ai_settings_3.py new file mode 100644 index 0000000..0d6a245 --- /dev/null +++ b/scripts/refactor_ai_settings_3.py @@ -0,0 +1,228 @@ +import sys + +with open("src/gui_2.py", "r", encoding="utf-8") as f: + content = f.read() + +# 1. Update _gui_func: +# Extract Persona out of Provider panel. I will create a new method _render_persona_selector_panel +old_gui_settings = """ if self.show_windows.get("AI Settings", False): + exp, opened = imgui.begin("AI Settings", self.show_windows["AI Settings"]) + self.show_windows["AI Settings"] = bool(opened) + if exp: + if imgui.collapsing_header("Provider & Model"): + self._render_provider_panel() + if imgui.collapsing_header("System Prompts"): + self._render_system_prompts_panel() + self._render_agent_tools_panel() + self._render_cache_panel() + + imgui.end() + if self.ui_separate_usage_analytics and self.show_windows.get("Usage Analytics", False): + exp, opened = imgui.begin("Usage Analytics", self.show_windows["Usage Analytics"]) + self.show_windows["Usage Analytics"] = bool(opened) + if exp: + self._render_usage_analytics_panel() + imgui.end()""" + +new_gui_settings = """ if self.show_windows.get("AI Settings", False): + exp, opened = imgui.begin("AI Settings", self.show_windows["AI Settings"]) + self.show_windows["AI Settings"] = bool(opened) + if exp: + self._render_persona_selector_panel() + if imgui.collapsing_header("Provider & Model"): + self._render_provider_panel() + if imgui.collapsing_header("System Prompts"): + self._render_system_prompts_panel() + self._render_agent_tools_panel() + + imgui.end() + if self.ui_separate_usage_analytics and self.show_windows.get("Usage Analytics", False): + exp, opened = imgui.begin("Usage Analytics", self.show_windows["Usage Analytics"]) + self.show_windows["Usage Analytics"] = bool(opened) + if exp: + self._render_usage_analytics_panel() + imgui.end()""" + +content = content.replace(old_gui_settings, new_gui_settings) + +# Update _render_usage_analytics_panel +old_usage = """ def _render_usage_analytics_panel(self) -> None: + if self.perf_profiling_enabled: self.perf_monitor.start_component("_render_usage_analytics_panel") + self._render_token_budget_panel() + imgui.separator() + self._render_tool_analytics_panel() + imgui.separator() + self._render_session_insights_panel() + if self.perf_profiling_enabled: self.perf_monitor.end_component("_render_usage_analytics_panel")""" + +new_usage = """ def _render_usage_analytics_panel(self) -> None: + if self.perf_profiling_enabled: self.perf_monitor.start_component("_render_usage_analytics_panel") + self._render_token_budget_panel() + imgui.separator() + self._render_cache_panel() + imgui.separator() + self._render_tool_analytics_panel() + imgui.separator() + self._render_session_insights_panel() + if self.perf_profiling_enabled: self.perf_monitor.end_component("_render_usage_analytics_panel")""" +content = content.replace(old_usage, new_usage) + +# Remove the persona block from _render_provider_panel and put it in _render_persona_selector_panel +old_persona_block = """ def _render_provider_panel(self) -> None: + if self.perf_profiling_enabled: self.perf_monitor.start_component("_render_provider_panel") + imgui.text("Persona") + if not hasattr(self, 'ui_active_persona'): + self.ui_active_persona = "" + personas = getattr(self.controller, 'personas', {}) + if imgui.begin_combo("##persona", self.ui_active_persona or "None"): + if imgui.selectable("None", not self.ui_active_persona)[0]: + self.ui_active_persona = "" + for pname in sorted(personas.keys()): + if imgui.selectable(pname, pname == self.ui_active_persona)[0]: + self.ui_active_persona = pname + if pname in personas: + persona = personas[pname] + self._editing_persona_name = persona.name + self._editing_persona_provider = persona.provider or "" + self._editing_persona_model = persona.model or "" + self._editing_persona_system_prompt = persona.system_prompt or "" + self._editing_persona_temperature = persona.temperature or 0.7 + self._editing_persona_max_tokens = persona.max_output_tokens or 4096 + self._editing_persona_tool_preset_id = persona.tool_preset or "" + self._editing_persona_bias_profile_id = persona.bias_profile or "" + import json + self._editing_persona_preferred_models = json.dumps(persona.preferred_models) if persona.preferred_models else "[]" + self._editing_persona_is_new = False + if persona.provider and persona.provider in self.controller.PROVIDERS: + self.current_provider = persona.provider + if persona.model: + self.current_model = persona.model + if persona.temperature is not None: + ai_client.temperature = persona.temperature + if persona.max_output_tokens: + ai_client.max_output_tokens = persona.max_output_tokens + if persona.system_prompt: + self.ui_project_system_prompt = persona.system_prompt + if persona.tool_preset: + self.ui_active_tool_preset = persona.tool_preset + ai_client.set_tool_preset(persona.tool_preset) + if persona.bias_profile: + self.ui_active_bias_profile = persona.bias_profile + ai_client.set_bias_profile(persona.bias_profile) + imgui.end_combo() + imgui.same_line() + if imgui.button("Manage Personas"): + self.show_persona_editor_window = True + if self.ui_active_persona and self.ui_active_persona in personas: + persona = personas[self.ui_active_persona] + self._editing_persona_name = persona.name + self._editing_persona_provider = persona.provider or "" + self._editing_persona_model = persona.model or "" + self._editing_persona_system_prompt = persona.system_prompt or "" + self._editing_persona_temperature = persona.temperature if persona.temperature is not None else 0.7 + self._editing_persona_max_tokens = persona.max_output_tokens if persona.max_output_tokens is not None else 4096 + self._editing_persona_tool_preset_id = persona.tool_preset or "" + self._editing_persona_bias_profile_id = persona.bias_profile or "" + self._editing_persona_preferred_models_list = list(persona.preferred_models) if persona.preferred_models else [] + self._editing_persona_scope = self.controller.persona_manager.get_persona_scope(persona.name) + self._editing_persona_is_new = False + else: + self._editing_persona_name = "" + self._editing_persona_provider = self.current_provider + self._editing_persona_model = self.current_model + self._editing_persona_system_prompt = "" + self._editing_persona_temperature = 0.7 + self._editing_persona_max_tokens = 4096 + self._editing_persona_tool_preset_id = "" + self._editing_persona_bias_profile_id = "" + self._editing_persona_preferred_models_list = [] + self._editing_persona_scope = "project" + self._editing_persona_is_new = True + imgui.separator() + imgui.text("Provider")""" + +new_persona_block = """ def _render_persona_selector_panel(self) -> None: + if self.perf_profiling_enabled: self.perf_monitor.start_component("_render_persona_selector_panel") + imgui.text("Persona") + if not hasattr(self, 'ui_active_persona'): + self.ui_active_persona = "" + personas = getattr(self.controller, 'personas', {}) + if imgui.begin_combo("##persona", self.ui_active_persona or "None"): + if imgui.selectable("None", not self.ui_active_persona)[0]: + self.ui_active_persona = "" + for pname in sorted(personas.keys()): + if imgui.selectable(pname, pname == self.ui_active_persona)[0]: + self.ui_active_persona = pname + if pname in personas: + persona = personas[pname] + self._editing_persona_name = persona.name + self._editing_persona_system_prompt = persona.system_prompt or "" + self._editing_persona_tool_preset_id = persona.tool_preset or "" + self._editing_persona_bias_profile_id = persona.bias_profile or "" + import copy + self._editing_persona_preferred_models_list = copy.deepcopy(persona.preferred_models) if persona.preferred_models else [] + self._editing_persona_is_new = False + + # Apply persona to current state immediately + if persona.preferred_models and len(persona.preferred_models) > 0: + first_model = persona.preferred_models[0] + if first_model.get("provider"): + self.current_provider = first_model.get("provider") + if first_model.get("model"): + self.current_model = first_model.get("model") + if first_model.get("temperature") is not None: + ai_client.temperature = first_model.get("temperature") + self.temperature = first_model.get("temperature") + if first_model.get("max_output_tokens"): + ai_client.max_output_tokens = first_model.get("max_output_tokens") + self.max_tokens = first_model.get("max_output_tokens") + if first_model.get("history_trunc_limit"): + self.history_trunc_limit = first_model.get("history_trunc_limit") + + if persona.system_prompt: + self.ui_project_system_prompt = persona.system_prompt + if persona.tool_preset: + self.ui_active_tool_preset = persona.tool_preset + ai_client.set_tool_preset(persona.tool_preset) + if persona.bias_profile: + self.ui_active_bias_profile = persona.bias_profile + ai_client.set_bias_profile(persona.bias_profile) + imgui.end_combo() + imgui.same_line() + if imgui.button("Manage Personas"): + self.show_persona_editor_window = True + if self.ui_active_persona and self.ui_active_persona in personas: + persona = personas[self.ui_active_persona] + self._editing_persona_name = persona.name + self._editing_persona_system_prompt = persona.system_prompt or "" + self._editing_persona_tool_preset_id = persona.tool_preset or "" + self._editing_persona_bias_profile_id = persona.bias_profile or "" + import copy + self._editing_persona_preferred_models_list = copy.deepcopy(persona.preferred_models) if persona.preferred_models else [] + self._editing_persona_scope = self.controller.persona_manager.get_persona_scope(persona.name) + self._editing_persona_is_new = False + else: + self._editing_persona_name = "" + self._editing_persona_system_prompt = "" + self._editing_persona_tool_preset_id = "" + self._editing_persona_bias_profile_id = "" + self._editing_persona_preferred_models_list = [{ + "provider": self.current_provider, + "model": self.current_model, + "temperature": getattr(self, "temperature", 0.7), + "max_output_tokens": getattr(self, "max_tokens", 4096), + "history_trunc_limit": getattr(self, "history_trunc_limit", 900000) + }] + self._editing_persona_scope = "project" + self._editing_persona_is_new = True + imgui.separator() + if self.perf_profiling_enabled: self.perf_monitor.end_component("_render_persona_selector_panel") + + def _render_provider_panel(self) -> None: + if self.perf_profiling_enabled: self.perf_monitor.start_component("_render_provider_panel") + imgui.text("Provider")""" +content = content.replace(old_persona_block, new_persona_block) + +with open("src/gui_2.py", "w", encoding="utf-8") as f: + f.write(content) +print("done gui updates")