diff --git a/gui_2.py b/gui_2.py index a09cf80..845b75b 100644 --- a/gui_2.py +++ b/gui_2.py @@ -86,6 +86,9 @@ class App: self.current_provider: str = ai_cfg.get("provider", "gemini") self.current_model: str = ai_cfg.get("model", "gemini-2.0-flash") self.available_models: list[str] = [] + self.temperature: float = ai_cfg.get("temperature", 0.0) + self.max_tokens: int = ai_cfg.get("max_tokens", 8192) + self.history_trunc_limit: int = ai_cfg.get("history_trunc_limit", 8000) projects_cfg = self.config.get("projects", {}) self.project_paths: list[str] = list(projects_cfg.get("paths", [])) @@ -176,6 +179,8 @@ class App: self._is_script_blinking = False self._script_blink_start_time = 0.0 + self._scroll_disc_to_bottom = False + session_logger.open_session() ai_client.set_provider(self.current_provider, self.current_model) ai_client.confirm_and_run_callback = self._confirm_and_run @@ -376,7 +381,13 @@ class App: disc_sec["auto_add"] = self.ui_auto_add_history def _flush_to_config(self): - self.config["ai"] = {"provider": self.current_provider, "model": self.current_model} + self.config["ai"] = { + "provider": self.current_provider, + "model": self.current_model, + "temperature": self.temperature, + "max_tokens": self.max_tokens, + "history_trunc_limit": self.history_trunc_limit, + } self.config["ai"]["system_prompt"] = self.ui_global_system_prompt self.config["projects"] = {"paths": self.project_paths, "active": self.active_project_path} theme.save_to_config(self.config) @@ -441,6 +452,8 @@ class App: self._pending_comms.clear() with self._pending_history_adds_lock: + if self._pending_history_adds: + self._scroll_disc_to_bottom = True for item in self._pending_history_adds: if item["role"] not in self.disc_roles: self.disc_roles.append(item["role"]) @@ -453,22 +466,22 @@ class App: _, self.show_windows[w] = imgui.menu_item(w, "", self.show_windows[w]) imgui.end_menu() if imgui.begin_menu("Project"): - if imgui.menu_item("Save All")[0]: + if imgui.menu_item("Save All", "", False)[0]: self._flush_to_project() self._save_active_project() self._flush_to_config() save_config(self.config) self.ai_status = "config saved" - if imgui.menu_item("Reset Session")[0]: + if imgui.menu_item("Reset Session", "", False)[0]: ai_client.reset_session() ai_client.clear_comms_log() self._tool_log.clear() self._comms_log.clear() self.ai_status = "session reset" self.ai_response = "" - if imgui.menu_item("Generate MD Only")[0]: + if imgui.menu_item("Generate MD Only", "", False)[0]: try: - md, path, _ = self._do_generate() + md, path, *_ = self._do_generate() self.last_md = md self.last_md_path = path self.ai_status = f"md written: {path.name}" @@ -535,7 +548,10 @@ class App: if imgui.button("Add Project"): r = hide_tk_root() - p = filedialog.askopenfilename(title="Select Project .toml", filetypes=[("TOML", "*.toml"), ("All", "*.*")]) + p = filedialog.askopenfilename( + title="Select Project .toml", + filetypes=[("TOML", "*.toml"), ("All", "*.*")], + ) r.destroy() if p and p not in self.project_paths: self.project_paths.append(p) @@ -626,7 +642,10 @@ class App: if imgui.button("Add Screenshot(s)"): r = hide_tk_root() - paths = filedialog.askopenfilenames() + paths = filedialog.askopenfilenames( + title="Select Screenshots", + filetypes=[("Images", "*.png *.jpg *.jpeg *.gif *.bmp *.webp"), ("All", "*.*")], + ) r.destroy() for p in paths: if p not in self.screenshots: self.screenshots.append(p) @@ -779,6 +798,9 @@ class App: imgui.separator() imgui.pop_id() + if self._scroll_disc_to_bottom: + imgui.set_scroll_here_y(1.0) + self._scroll_disc_to_bottom = False imgui.end_child() imgui.end() @@ -809,6 +831,11 @@ class App: ai_client.reset_session() ai_client.set_provider(self.current_provider, m) imgui.end_list_box() + imgui.separator() + imgui.text("Parameters") + ch, self.temperature = imgui.slider_float("Temperature", self.temperature, 0.0, 2.0, "%.2f") + ch, self.max_tokens = imgui.input_int("Max Tokens (Output)", self.max_tokens, 1024) + ch, self.history_trunc_limit = imgui.input_int("History Truncation Limit", self.history_trunc_limit, 1024) imgui.end() # ---- Message @@ -820,7 +847,7 @@ class App: if imgui.button("Gen + Send"): if not (self.send_thread and self.send_thread.is_alive()): try: - md, path, file_items = self._do_generate() + md, path, file_items, stable_md, disc_text = self._do_generate() self.last_md = md self.last_md_path = path self.last_file_items = file_items @@ -833,6 +860,7 @@ class App: csp = filter(bool, [self.ui_global_system_prompt.strip(), self.ui_project_system_prompt.strip()]) ai_client.set_custom_system_prompt("\n\n".join(csp)) + def do_send(): if self.ui_auto_add_history: with self._pending_history_adds_lock: @@ -865,7 +893,7 @@ class App: imgui.same_line() if imgui.button("MD Only"): try: - md, path, _ = self._do_generate() + md, path, *_ = self._do_generate() self.last_md = md self.last_md_path = path self.ai_status = f"md written: {path.name}" @@ -1247,22 +1275,29 @@ class App: if font_path and Path(font_path).exists(): hello_imgui.load_font(font_path, font_size) + def _post_init(self): + theme.apply_current() + def run(self): theme.load_from_config(self.config) - + self.runner_params = hello_imgui.RunnerParams() self.runner_params.app_window_params.window_title = "manual slop" self.runner_params.app_window_params.window_geometry.size = (1680, 1200) self.runner_params.imgui_window_params.enable_viewports = True self.runner_params.imgui_window_params.default_imgui_window_type = hello_imgui.DefaultImGuiWindowType.provide_full_screen_dock_space + self.runner_params.ini_folder_type = hello_imgui.IniFolderType.current_folder + self.runner_params.ini_filename = "manualslop_layout.ini" self.runner_params.callbacks.show_gui = self._gui_func self.runner_params.callbacks.load_additional_fonts = self._load_fonts + self.runner_params.callbacks.post_init = self._post_init self._fetch_models(self.current_provider) immapp.run(self.runner_params) # On exit + ai_client.cleanup() # Destroy active API caches to stop billing self._flush_to_project() self._save_active_project() self._flush_to_config() diff --git a/manualslop_layout.ini b/manualslop_layout.ini new file mode 100644 index 0000000..f9dc2b1 --- /dev/null +++ b/manualslop_layout.ini @@ -0,0 +1,116 @@ +;;; !!! This configuration is handled by HelloImGui and stores several Ini Files, separated by markers like this: + ;;;<<>>;;; + +;;;<<>>;;; +[Window][Debug##Default] +Pos=60,60 +Size=400,400 +Collapsed=0 + +[Window][Projects] +Pos=209,396 +Size=387,337 +Collapsed=0 +DockId=0x00000014,0 + +[Window][Files] +Pos=0,0 +Size=207,1200 +Collapsed=0 +DockId=0x00000011,0 + +[Window][Screenshots] +Pos=209,0 +Size=387,171 +Collapsed=0 +DockId=0x00000015,0 + +[Window][Discussion History] +Pos=598,128 +Size=712,619 +Collapsed=0 +DockId=0x0000000E,0 + +[Window][Provider] +Pos=209,913 +Size=387,287 +Collapsed=0 +DockId=0x0000000A,0 + +[Window][Message] +Pos=598,749 +Size=712,451 +Collapsed=0 +DockId=0x0000000C,0 + +[Window][Response] +Pos=209,735 +Size=387,176 +Collapsed=0 +DockId=0x00000010,0 + +[Window][Tool Calls] +Pos=1312,733 +Size=368,144 +Collapsed=0 +DockId=0x00000008,0 + +[Window][Comms History] +Pos=1312,879 +Size=368,321 +Collapsed=0 +DockId=0x00000006,0 + +[Window][System Prompts] +Pos=1312,0 +Size=368,731 +Collapsed=0 +DockId=0x00000007,0 + +[Window][Theme] +Pos=209,173 +Size=387,221 +Collapsed=0 +DockId=0x00000016,0 + +[Window][Text Viewer - Entry #7] +Pos=379,324 +Size=900,700 +Collapsed=0 + +[Docking][Data] +DockSpace ID=0xAFC85805 Window=0x079D3A04 Pos=138,161 Size=1680,1200 Split=X + DockNode ID=0x00000011 Parent=0xAFC85805 SizeRef=207,1200 Selected=0x0469CA7A + DockNode ID=0x00000012 Parent=0xAFC85805 SizeRef=1559,1200 Split=X + DockNode ID=0x00000003 Parent=0x00000012 SizeRef=1189,1200 Split=X + DockNode ID=0x00000001 Parent=0x00000003 SizeRef=387,1200 Split=Y Selected=0x8CA2375C + DockNode ID=0x00000009 Parent=0x00000001 SizeRef=405,911 Split=Y Selected=0x8CA2375C + DockNode ID=0x0000000F Parent=0x00000009 SizeRef=405,733 Split=Y Selected=0x8CA2375C + DockNode ID=0x00000013 Parent=0x0000000F SizeRef=405,394 Split=Y Selected=0x8CA2375C + DockNode ID=0x00000015 Parent=0x00000013 SizeRef=405,171 Selected=0xDF822E02 + DockNode ID=0x00000016 Parent=0x00000013 SizeRef=405,221 Selected=0x8CA2375C + DockNode ID=0x00000014 Parent=0x0000000F SizeRef=405,337 Selected=0xDA22FEDA + DockNode ID=0x00000010 Parent=0x00000009 SizeRef=405,176 Selected=0x0D5A5273 + DockNode ID=0x0000000A Parent=0x00000001 SizeRef=405,287 Selected=0xA07B5F14 + DockNode ID=0x00000002 Parent=0x00000003 SizeRef=800,1200 Split=Y + DockNode ID=0x0000000B Parent=0x00000002 SizeRef=1010,747 Split=Y + DockNode ID=0x0000000D Parent=0x0000000B SizeRef=1010,126 CentralNode=1 + DockNode ID=0x0000000E Parent=0x0000000B SizeRef=1010,619 Selected=0x5D11106F + DockNode ID=0x0000000C Parent=0x00000002 SizeRef=1010,451 Selected=0x66CFB56E + DockNode ID=0x00000004 Parent=0x00000012 SizeRef=368,1200 Split=Y Selected=0xDD6419BC + DockNode ID=0x00000005 Parent=0x00000004 SizeRef=261,877 Split=Y Selected=0xDD6419BC + DockNode ID=0x00000007 Parent=0x00000005 SizeRef=261,731 Selected=0xDD6419BC + DockNode ID=0x00000008 Parent=0x00000005 SizeRef=261,144 Selected=0x1D56B311 + DockNode ID=0x00000006 Parent=0x00000004 SizeRef=261,321 Selected=0x8B4EBFA6 + +;;;<<>>;;; +;;;<<>>;;; +[Layout] +Name=Default +[StatusBar] +Show=false +ShowFps=true +[Theme] +Name=DarculaDarker +;;;<<>>;;; +{"gImGuiSplitIDs":{"MainDockSpace":2949142533}} diff --git a/theme_2.py b/theme_2.py index fedffe1..2f15470 100644 --- a/theme_2.py +++ b/theme_2.py @@ -5,7 +5,7 @@ Theming support for manual_slop GUI — imgui-bundle port. Replaces theme.py (DearPyGui-specific) with imgui-bundle equivalents. Palettes are applied via imgui.get_style().set_color_() calls. Font loading uses hello_imgui.load_font(). -Scale uses imgui.get_io().font_global_scale. +Scale uses imgui.get_style().font_scale_main. """ from imgui_bundle import imgui, hello_imgui @@ -238,11 +238,11 @@ def apply(palette_name: str): def set_scale(factor: float): - """Set the global font scale factor.""" + """Set the global font/UI scale factor.""" global _current_scale _current_scale = factor - io = imgui.get_io() - io.font_global_scale = factor + style = imgui.get_style() + style.font_scale_main = factor def save_to_config(config: dict): @@ -263,6 +263,12 @@ def load_from_config(config: dict): _current_font_size = float(t.get("font_size", 16.0)) _current_scale = float(t.get("scale", 1.0)) + # Don't apply here — imgui context may not exist yet. + # Call apply_current() after imgui is initialised. + + +def apply_current(): + """Apply the loaded palette and scale. Call after imgui context exists.""" apply(_current_palette) set_scale(_current_scale)