From 643f36e7d19f9480276b637a2c03c90f078821ea Mon Sep 17 00:00:00 2001 From: Ed_ Date: Tue, 12 May 2026 01:03:16 -0400 Subject: [PATCH] beginning to chunk up _gui_func --- src/gui_2.py | 1574 +++++++++++++++++++++++++------------------------- 1 file changed, 788 insertions(+), 786 deletions(-) diff --git a/src/gui_2.py b/src/gui_2.py index 1884ce9..416202d 100644 --- a/src/gui_2.py +++ b/src/gui_2.py @@ -811,6 +811,792 @@ class App: if not history: imgui.text("No history available.") else: iterate_history() + def _gui_func__abusrd_try_scope(self) -> None: + self.perf_monitor.start_frame() + self._autofocus_response_tab = self.controller._autofocus_response_tab + + #region: Process GUI task queue + # DEBUG: Check if tasks exist before processing + if hasattr(self, 'controller') and hasattr(self.controller, '_pending_gui_tasks'): + pending_count = len(self.controller._pending_gui_tasks) + if pending_count > 0: + sys.stderr.write(f"[DEBUG gui_2] _gui_func: found {pending_count} pending tasks\n") + sys.stderr.flush() + self._process_pending_gui_tasks() + self._process_pending_history_adds() + if self.controller._process_pending_tool_calls(): + self._tool_log_dirty = True + #endregion: Process GUI task queue + + self._render_track_proposal_modal() + self._render_patch_modal() + self._render_base_prompt_diff_modal() + self._render_save_preset_modal() + self._render_save_workspace_profile_modal() + self._render_add_context_files_modal() + self._render_preset_manager_window() + self._render_tool_preset_manager_window() + self._render_persona_editor_window() + + # Auto-save (every 60s) + now = time.time() + if now - self._last_autosave >= self._autosave_interval: + self._last_autosave = now + try: + self._flush_to_project() + self._flush_to_config() + models.save_config(self.config) + except Exception: + pass # silent — don't disrupt the GUI loop + # Sync pending comms + with self._pending_comms_lock: + if self._pending_comms: + if self.ui_auto_scroll_comms: + self._scroll_comms_to_bottom = True + self._comms_log_dirty = True + for c in self._pending_comms: + self._comms_log.append(c) + self._pending_comms.clear() + + if self.ui_focus_agent != self._last_ui_focus_agent: + self._comms_log_dirty = True + self._tool_log_dirty = True + self._last_ui_focus_agent = self.ui_focus_agent + + if self._comms_log_dirty: + if self.is_viewing_prior_session: + self._comms_log_cache = self.prior_session_entries + else: + log_raw = list(self._comms_log) + if self.ui_focus_agent: + self._comms_log_cache = [e for e in log_raw if e.get("source_tier", "").startswith(self.ui_focus_agent)] + else: + self._comms_log_cache = log_raw + self._comms_log_dirty = False + + if self._tool_log_dirty: + if self.is_viewing_prior_session: + self._tool_log_cache = self.prior_tool_calls + else: + log_raw = list(self._tool_log) + if self.ui_focus_agent: + self._tool_log_cache = [e for e in log_raw if e.get("source_tier", "").startswith(self.ui_focus_agent)] + else: + self._tool_log_cache = log_raw + self._tool_log_dirty = False + + #region: Project Settings + if self.show_windows.get("Project Settings", False): + with imscope.window("Project Settings", self.show_windows["Project Settings"]) as (exp, opened): + self.show_windows["Project Settings"] = bool(opened) + if exp and imscope.tab_bar('context_hub_tabs'): + if imscope.tab_item('Projects'): self._render_projects_panel() + if imscope.tab_item('Paths'): self._render_paths_panel() + #endregion: Project Settings + + #region: Files & Media window + if self.show_windows.get("Files & Media", False): + exp, opened = imgui.begin("Files & Media", self.show_windows["Files & Media"]) + self.show_windows["Files & Media"] = bool(opened) + if opened: + if exp: + avail = imgui.get_content_region_avail().y + if not hasattr(self, 'files_screenshots_split'): + self.files_screenshots_split = 0.65 + split_y = int(avail * self.files_screenshots_split) + if imgui.collapsing_header("Files", imgui.TreeNodeFlags_.default_open): + imgui.begin_child("Files_child", imgui.ImVec2(-1, split_y), True) + if not hasattr(self, 'files_last_selected'): + self.files_last_selected = -1 + if imgui.begin_table("files_table", 5, imgui.TableFlags_.resizable | imgui.TableFlags_.borders): + imgui.table_setup_column("", imgui.TableColumnFlags_.width_fixed, 20) + imgui.table_setup_column("Path", imgui.TableColumnFlags_.width_stretch) + imgui.table_setup_column("Agg", imgui.TableColumnFlags_.width_fixed, 0) + imgui.table_setup_column("Full", imgui.TableColumnFlags_.width_fixed, 0) + imgui.table_setup_column("Cache", imgui.TableColumnFlags_.width_fixed, 0) + imgui.table_headers_row() + self.files.sort(key=lambda f: f.path.lower() if hasattr(f, 'path') else str(f).lower()) + for i, f_item in enumerate(self.files): + imgui.table_next_row() + imgui.table_set_column_index(0) + clicked, f_item.selected = imgui.checkbox(f"##{i}", f_item.selected) + if clicked: + if (imgui.is_key_down(imgui.Key.left_shift) or imgui.is_key_down(imgui.Key.right_shift)) and self.files_last_selected >= 0: + start_i = min(self.files_last_selected, i) + end_i = max(self.files_last_selected, i) + for j in range(start_i, end_i + 1): + self.files[j].selected = True + self.files_last_selected = i + imgui.table_set_column_index(1) + imgui.text(f_item.path if hasattr(f_item, 'path') else str(f_item)) + imgui.table_set_column_index(2) + if f_item.auto_aggregate: + imgui.text_colored(imgui.ImVec4(0.3, 0.8, 1, 1), "A") + else: + imgui.text_disabled(" ") + imgui.same_line(spacing=1) + if imgui.invisible_button(f"agg{i}", imgui.ImVec2(15, 15)): + f_item.auto_aggregate = not f_item.auto_aggregate + if f_item.auto_aggregate: + f_item.force_full = False + imgui.table_set_column_index(3) + if f_item.force_full: + imgui.text_colored(imgui.ImVec4(1, 0.6, 0.3, 1), "F") + else: + imgui.text_disabled(" ") + imgui.same_line(spacing=1) + if imgui.invisible_button(f"full{i}", imgui.ImVec2(15, 15)): + f_item.force_full = not f_item.force_full + if f_item.force_full: + f_item.auto_aggregate = False + imgui.table_set_column_index(4) + fpath = f_item.path if hasattr(f_item, 'path') else str(f_item) + is_cached = any(fpath in c for c in getattr(self, '_cached_files', [])) + if is_cached: + imgui.text_colored(imgui.ImVec4(0, 1, 0, 1), "Y") + else: + imgui.text_colored(imgui.ImVec4(0.5, 0.5, 0.5, 1), "-") + imgui.end_table() + if imgui.button("Add Files##addf"): + r = hide_tk_root() + paths = filedialog.askopenfilenames() + r.destroy() + for p in paths: + if p not in [f.path if hasattr(f, 'path') else f for f in self.files]: + self.files.append(models.FileItem(path=p)) + imgui.same_line() + if imgui.button("Sel All##selall"): + for f in self.files: + f.selected = True + imgui.same_line() + if imgui.button("Unsel##unselall"): + for f in self.files: + f.selected = False + imgui.same_line() + if imgui.button("None##nonesel"): + for f in self.files: + if f.selected: + f.auto_aggregate = False + f.force_full = False + imgui.same_line() + if imgui.button("Agg##aggsel"): + for f in self.files: + if f.selected: + f.auto_aggregate = True + f.force_full = False + imgui.same_line() + if imgui.button("Full##fullsel"): + for f in self.files: + if f.selected: + f.force_full = True + f.auto_aggregate = False + imgui.same_line() + if imgui.button("Del##dels"): + self.files = [f for f in self.files if not f.selected] + imgui.end_child() + imgui.separator() + if imgui.collapsing_header("Screenshots", imgui.TreeNodeFlags_.default_open): + imgui.begin_child("Shots_child", imgui.ImVec2(-1, -1), True) + for i, s in enumerate(self.screenshots): + if imgui.button(f"x##s{i}"): + self.screenshots.pop(i) + break + imgui.same_line() + imgui.text(s) + if imgui.button("Add Screenshots##adds"): + r = hide_tk_root() + paths = filedialog.askopenfilenames(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) + imgui.end_child() + imgui.end() + #endregion: Files & Media window + + #region: AI Settings + if self.show_windows.get("AI Settings", False): + with imscope.window("AI Settings", self.show_windows["AI Settings"]) as (exp, opened): + 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() + if imgui.collapsing_header("RAG Settings"): + self._render_rag_panel() + self._render_agent_tools_panel() + + 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() + if self.show_windows.get("MMA Dashboard", False): + exp, opened = imgui.begin("MMA Dashboard", self.show_windows["MMA Dashboard"]) + self.show_windows["MMA Dashboard"] = bool(opened) + if exp: + if self.perf_profiling_enabled: self.perf_monitor.start_component("_render_mma_dashboard") + self._render_mma_dashboard() + if self.perf_profiling_enabled: self.perf_monitor.end_component("_render_mma_dashboard") + imgui.end() + #endregion: AI Settings + + #region: Seprate Task Dag to Tier 4 + if self.ui_separate_task_dag and self.show_windows.get("Task DAG", False): + exp, opened = imgui.begin("Task DAG", self.show_windows["Task DAG"]) + self.show_windows["Task DAG"] = bool(opened) + if exp: + self._render_task_dag_panel() + imgui.end() + + if self.ui_separate_tier1 and self.show_windows.get("Tier 1: Strategy", False): + exp, opened = imgui.begin("Tier 1: Strategy", self.show_windows["Tier 1: Strategy"]) + self.show_windows["Tier 1: Strategy"] = bool(opened) + if exp: + self._render_tier_stream_panel("Tier 1", "Tier 1") + imgui.end() + + if self.ui_separate_tier2 and self.show_windows.get("Tier 2: Tech Lead", False): + exp, opened = imgui.begin("Tier 2: Tech Lead", self.show_windows["Tier 2: Tech Lead"]) + self.show_windows["Tier 2: Tech Lead"] = bool(opened) + if exp: + self._render_tier_stream_panel("Tier 2", "Tier 2 (Tech Lead)") + imgui.end() + + if self.ui_separate_tier3 and self.show_windows.get("Tier 3: Workers", False): + exp, opened = imgui.begin("Tier 3: Workers", self.show_windows["Tier 3: Workers"]) + self.show_windows["Tier 3: Workers"] = bool(opened) + if exp: + self._render_tier_stream_panel("Tier 3", None) + imgui.end() + + if self.ui_separate_tier4 and self.show_windows.get("Tier 4: QA", False): + exp, opened = imgui.begin("Tier 4: QA", self.show_windows["Tier 4: QA"]) + self.show_windows["Tier 4: QA"] = bool(opened) + if exp: + self._render_tier_stream_panel("Tier 4", "Tier 4 (QA)") + imgui.end() + #endregion: Separate Task Dag to Tier 4 + + if self.show_windows.get("Theme", False): + self._render_theme_panel() + + #region: Discussion Hub + if self.show_windows.get("Discussion Hub", False): + exp, opened = imgui.begin("Discussion Hub", self.show_windows["Discussion Hub"]) + self.show_windows["Discussion Hub"] = bool(opened) + if exp: + if imgui.begin_tab_bar("discussion_hub_tabs"): + if imgui.begin_tab_item("Discussion")[0]: + self._render_discussion_tab() + imgui.end_tab_item() + if imgui.begin_tab_item("Context Composition")[0]: + self._render_context_composition_panel() + imgui.end_tab_item() + if imgui.begin_tab_item("Snapshot")[0]: + self._render_snapshot_tab() + imgui.end_tab_item() + if imgui.begin_tab_item("Takes")[0]: + self._render_takes_panel() + imgui.end_tab_item() + imgui.end_tab_bar() + imgui.end() + #endregion: Discussion Hub + + #region: Operations Hub + if self.show_windows.get("Operations Hub", False): + exp, opened = imgui.begin("Operations Hub", self.show_windows["Operations Hub"]) + self.show_windows["Operations Hub"] = bool(opened) + if exp: + imgui.push_style_var(imgui.StyleVar_.item_spacing, imgui.ImVec2(10, 4)) + ch1, self.ui_separate_tool_calls_panel = imgui.checkbox("Pop Out Tool Calls", self.ui_separate_tool_calls_panel) + if ch1: self.show_windows["Tool Calls"] = self.ui_separate_tool_calls_panel + imgui.same_line() + ch2, self.ui_separate_usage_analytics = imgui.checkbox("Pop Out Usage Analytics", self.ui_separate_usage_analytics) + if ch2: self.show_windows["Usage Analytics"] = self.ui_separate_usage_analytics + imgui.same_line() + ch3, self.ui_separate_external_tools = imgui.checkbox('Pop Out External Tools', self.ui_separate_external_tools) + if ch3: self.show_windows['External Tools'] = self.ui_separate_external_tools + imgui.pop_style_var() + + show_tc_tab = not self.ui_separate_tool_calls_panel + show_usage_tab = not self.ui_separate_usage_analytics + + if imgui.begin_tab_bar("ops_tabs"): + if imgui.begin_tab_item("Comms History")[0]: + self._render_comms_history_panel() + imgui.end_tab_item() + if show_tc_tab: + if imgui.begin_tab_item("Tool Calls")[0]: + self._render_tool_calls_panel() + imgui.end_tab_item() + if show_usage_tab: + if imgui.begin_tab_item("Usage Analytics")[0]: + self._render_usage_analytics_panel() + imgui.end_tab_item() + if not self.ui_separate_external_tools: + if imgui.begin_tab_item("External Tools")[0]: + self._render_external_tools_panel() + imgui.separator() + imgui.text("") + try: + self._render_external_editor_panel() + except Exception as e: + imgui.text_colored(vec4(1, 0.3, 0.3, 1), f"Error: {str(e)}") + imgui.end_tab_item() + if imgui.begin_tab_item("Workspace Layouts")[0]: + imgui.text("Experimental: Auto-switch layout by Tier") + ch, self.controller.ui_auto_switch_layout = imgui.checkbox("Enable Auto-Switch", self.controller.ui_auto_switch_layout) + if self.controller.ui_auto_switch_layout: + imgui.separator() + imgui.text("Tier Bindings (select profile for each tier)") + profiles = [""] + [p.name for p in self.controller.workspace_profiles.values()] + for t in ["Tier 1", "Tier 2", "Tier 3", "Tier 4"]: + curr = self.controller.ui_tier_layout_bindings.get(t, "") + idx = profiles.index(curr) if curr in profiles else 0 + ch_combo, new_idx = imgui.combo(t, idx, profiles) + if ch_combo: + self.controller.ui_tier_layout_bindings[t] = profiles[new_idx] + imgui.end_tab_item() + imgui.end_tab_bar() + imgui.end() + #endregion: Operations Hub + + #region: Separate Message, Response, Tool Calls, External Tools + if self.ui_separate_message_panel and self.show_windows.get("Message", False): + exp, opened = imgui.begin("Message", self.show_windows["Message"]) + self.show_windows["Message"] = bool(opened) + if exp: + self._render_message_panel() + imgui.end() + + if self.ui_separate_response_panel and self.show_windows.get("Response", False): + exp, opened = imgui.begin("Response", self.show_windows["Response"]) + self.show_windows["Response"] = bool(opened) + if exp: + self._render_response_panel() + imgui.end() + + if self.ui_separate_tool_calls_panel and self.show_windows.get("Tool Calls", False): + exp, opened = imgui.begin("Tool Calls", self.show_windows["Tool Calls"]) + self.show_windows["Tool Calls"] = bool(opened) + if exp: + self._render_tool_calls_panel() + imgui.end() + + if self.ui_separate_external_tools and self.show_windows.get('External Tools', False): + exp, opened = imgui.begin('External Tools', self.show_windows['External Tools']) + self.show_windows['External Tools'] = bool(opened) + if exp: + self._render_external_tools_panel() + imgui.end() + + if self.show_windows.get("Log Management", False): + if self.perf_profiling_enabled: self.perf_monitor.start_component("_render_log_management") + self._render_log_management() + if self.perf_profiling_enabled: self.perf_monitor.end_component("_render_log_management") + #endregion: Separate Message, Response, Tool Calls, External Tools + + if self.show_windows.get("Diagnostics", False): + self._render_diagnostics_panel() + + self.perf_monitor.end_frame() + + # Modals / Popups + + with self._pending_dialog_lock: + dlg = self._pending_dialog + if dlg: + if not self._pending_dialog_open: + imgui.open_popup("Approve PowerShell Command") + self._pending_dialog_open = True + else: + self._pending_dialog_open = False + + if imgui.begin_popup_modal("Approve PowerShell Command", None, imgui.WindowFlags_.always_auto_resize)[0]: + if not dlg: + imgui.close_current_popup() + else: + imgui.text("The AI wants to run the following PowerShell script:") + imgui.text_colored(vec4(200, 200, 100), f"base_dir: {dlg._base_dir}") + imgui.separator() + # Checkbox to toggle full preview inside modal + _, self.show_text_viewer = imgui.checkbox("Show Full Preview", self.show_text_viewer) + if self.show_text_viewer: + imgui.begin_child("preview_child", imgui.ImVec2(600, 300), True) + imgui.text_unformatted(dlg._script) + imgui.end_child() + else: + ch, dlg._script = imgui.input_text_multiline("##confirm_script", dlg._script, imgui.ImVec2(-1, 200)) + imgui.separator() + if imgui.button("Approve & Run", imgui.ImVec2(120, 0)): + with dlg._condition: + dlg._approved = True + dlg._done = True + dlg._condition.notify_all() + with self._pending_dialog_lock: + self._pending_dialog = None + imgui.close_current_popup() + imgui.same_line() + if imgui.button("Reject", imgui.ImVec2(120, 0)): + with dlg._condition: + dlg._approved = False + dlg._done = True + dlg._condition.notify_all() + with self._pending_dialog_lock: + self._pending_dialog = None + imgui.close_current_popup() + imgui.end_popup() + + if self._pending_ask_dialog: + if not self._ask_dialog_open: + imgui.open_popup("Approve Tool Execution") + self._ask_dialog_open = True + else: + self._ask_dialog_open = False + + if imgui.begin_popup_modal("Approve Tool Execution", None, imgui.WindowFlags_.always_auto_resize)[0]: + if not self._pending_ask_dialog or self._ask_tool_data is None: + imgui.close_current_popup() + else: + tool_name = self._ask_tool_data.get("tool", "unknown") + tool_args = self._ask_tool_data.get("args", {}) + imgui.text("The AI wants to execute a tool:") + imgui.text_colored(vec4(200, 200, 100), f"Tool: {tool_name}") + imgui.separator() + imgui.text("Arguments:") + imgui.begin_child("ask_args_child", imgui.ImVec2(400, 200), True) + imgui.text_unformatted(json.dumps(tool_args, indent=2)) + imgui.end_child() + imgui.separator() + if imgui.button("Approve", imgui.ImVec2(120, 0)): + self._handle_approve_ask() + imgui.close_current_popup() + imgui.same_line() + if imgui.button("Deny", imgui.ImVec2(120, 0)): + self._handle_reject_ask() + imgui.close_current_popup() + imgui.end_popup() + + #region: MMA Step Approval Modal + if self._pending_mma_approvals: + if not self._mma_approval_open: + imgui.open_popup("MMA Step Approval") + self._mma_approval_open = True + self._mma_approval_edit_mode = False + self._mma_approval_payload = self._pending_mma_approvals[0].get("payload", "") + else: + self._mma_approval_open = False + if imgui.begin_popup_modal("MMA Step Approval", None, imgui.WindowFlags_.always_auto_resize)[0]: + if not self._pending_mma_approvals: + imgui.close_current_popup() + else: + ticket_id = self._pending_mma_approvals[0].get("ticket_id", "??") + imgui.text(f"Ticket {ticket_id} is waiting for tool execution approval.") + imgui.separator() + if self._mma_approval_edit_mode: + imgui.text("Edit Raw Payload (Manual Memory Mutation):") + _, self._mma_approval_payload = imgui.input_text_multiline("##mma_payload", self._mma_approval_payload, imgui.ImVec2(600, 400)) + else: + imgui.text("Proposed Tool Call:") + imgui.begin_child("mma_preview", imgui.ImVec2(600, 300), True) + imgui.text_unformatted(str(self._pending_mma_approvals[0].get("payload", ""))) + imgui.end_child() + imgui.separator() + if imgui.button("Approve", imgui.ImVec2(120, 0)): + self._handle_mma_respond(approved=True, payload=self._mma_approval_payload) + imgui.close_current_popup() + imgui.same_line() + if imgui.button("Edit Payload" if not self._mma_approval_edit_mode else "Show Original", imgui.ImVec2(120, 0)): + self._mma_approval_edit_mode = not self._mma_approval_edit_mode + imgui.same_line() + if imgui.button("Abort Ticket", imgui.ImVec2(120, 0)): + self._handle_mma_respond(approved=False) + imgui.close_current_popup() + imgui.end_popup() + #endregion: MMA Step Approval Modal + + #region: MMA Spawn Approval Modal + if self._pending_mma_spawns: + if not self._mma_spawn_open: + imgui.open_popup("MMA Spawn Approval") + self._mma_spawn_open = True + self._mma_spawn_edit_mode = False + self._mma_spawn_prompt = self._pending_mma_spawns[0].get("prompt", "") + self._mma_spawn_context = self._pending_mma_spawns[0].get("context_md", "") + else: + self._mma_spawn_open = False + + if imgui.begin_popup_modal("MMA Spawn Approval", None, imgui.WindowFlags_.always_auto_resize)[0]: + if not self._pending_mma_spawns: + imgui.close_current_popup() + else: + role = self._pending_mma_spawns[0].get("role", "??") + ticket_id = self._pending_mma_spawns[0].get("ticket_id", "??") + imgui.text(f"Spawning {role} for Ticket {ticket_id}") + imgui.separator() + if self._mma_spawn_edit_mode: + imgui.text("Edit Prompt:") + _, self._mma_spawn_prompt = imgui.input_text_multiline("##spawn_prompt", self._mma_spawn_prompt, imgui.ImVec2(800, 200)) + imgui.text("Edit Context MD:") + _, self._mma_spawn_context = imgui.input_text_multiline("##spawn_context", self._mma_spawn_context, imgui.ImVec2(800, 300)) + else: + imgui.text("Proposed Prompt:") + imgui.begin_child("spawn_prompt_preview", imgui.ImVec2(800, 150), True) + imgui.text_unformatted(self._mma_spawn_prompt) + imgui.end_child() + imgui.text("Proposed Context MD:") + imgui.begin_child("spawn_context_preview", imgui.ImVec2(800, 250), True) + imgui.text_unformatted(self._mma_spawn_context) + imgui.end_child() + imgui.separator() + if imgui.button("Approve", imgui.ImVec2(120, 0)): + self._handle_mma_respond(approved=True, prompt=self._mma_spawn_prompt, context_md=self._mma_spawn_context) + imgui.close_current_popup() + imgui.same_line() + if imgui.button("Edit Mode" if not self._mma_spawn_edit_mode else "Preview Mode", imgui.ImVec2(120, 0)): + self._mma_spawn_edit_mode = not self._mma_spawn_edit_mode + imgui.same_line() + if imgui.button("Abort", imgui.ImVec2(120, 0)): + self._handle_mma_respond(approved=False, abort=True) + imgui.close_current_popup() + imgui.end_popup() + #endregion: MMA Spawn Approval Modal + + #region: Cycle Detected Popup + if imgui.begin_popup_modal("Cycle Detected!", None, imgui.WindowFlags_.always_auto_resize)[0]: + imgui.text_colored(imgui.ImVec4(1, 0.3, 0.3, 1), "The dependency graph contains a cycle!") + imgui.text("Please remove the circular dependency.") + if imgui.button("OK"): + imgui.close_current_popup() + imgui.end_popup() + if self.show_script_output: + if self._trigger_script_blink: + self._trigger_script_blink = False + self._is_script_blinking = True + self._script_blink_start_time = time.time() + try: + imgui.set_window_focus("Last Script Output") # type: ignore[call-arg] + except Exception: + pass + if self._is_script_blinking: + elapsed = time.time() - self._script_blink_start_time + if elapsed > 1.5: + self._is_script_blinking = False + else: + val = math.sin(elapsed * 8 * math.pi) + alpha = 60/255 if val > 0 else 0 + imgui.push_style_color(imgui.Col_.frame_bg, vec4(0, 100, 255, alpha)) + imgui.push_style_color(imgui.Col_.child_bg, vec4(0, 100, 255, alpha)) + imgui.set_next_window_size(imgui.ImVec2(800, 600), imgui.Cond_.first_use_ever) + expanded, opened = imgui.begin("Last Script Output", self.show_script_output) + self.show_script_output = bool(opened) + if expanded: + imgui.text("Script:") + imgui.same_line() + self._render_text_viewer("Last Script", self.ui_last_script_text) + if self.ui_word_wrap: + imgui.begin_child("lso_s_wrap", imgui.ImVec2(-1, 200), True) + imgui.push_text_wrap_pos(imgui.get_content_region_avail().x) + imgui.text(self.ui_last_script_text) + imgui.pop_text_wrap_pos() + imgui.end_child() + else: + imgui.input_text_multiline("##lso_s", self.ui_last_script_text, imgui.ImVec2(-1, 200), imgui.InputTextFlags_.read_only) + imgui.separator() + imgui.text("Output:") + imgui.same_line() + self._render_text_viewer("Last Output", self.ui_last_script_output) + if self.ui_word_wrap: + imgui.begin_child("lso_o_wrap", imgui.ImVec2(-1, -1), True) + imgui.push_text_wrap_pos(imgui.get_content_region_avail().x) + imgui.text(self.ui_last_script_output) + imgui.pop_text_wrap_pos() + imgui.end_child() + else: + imgui.input_text_multiline("##lso_o", self.ui_last_script_output, imgui.ImVec2(-1, -1), imgui.InputTextFlags_.read_only) + if self._is_script_blinking: + imgui.pop_style_color(2) + imgui.end() + if self.show_text_viewer: + imgui.set_next_window_size(imgui.ImVec2(900, 700), imgui.Cond_.first_use_ever) + expanded, opened = imgui.begin(f"Text Viewer - {self.text_viewer_title}", self.show_text_viewer) + self.show_text_viewer = bool(opened) + if not opened: + self.ui_editing_slices_file = None + self._slice_sel_start = -1 + self._slice_sel_end = -1 + + if expanded: + if self.ui_editing_slices_file is not None: + imgui.text_colored(C_IN, "Slice Management (Click-drag lines to select range)") + if imgui.button("Add Selection as Slice"): + if self._slice_sel_start != -1 and self._slice_sel_end != -1: + s_line = min(self._slice_sel_start, self._slice_sel_end) + e_line = max(self._slice_sel_start, self._slice_sel_end) + from src.fuzzy_anchor import FuzzyAnchor + slice_data = FuzzyAnchor.create_slice(self.text_viewer_content, s_line, e_line) + slice_data['tag'] = "" + slice_data['comment'] = "" + self.ui_editing_slices_file.custom_slices.append(slice_data) + self._slice_sel_start = -1 + self._slice_sel_end = -1 + imgui.same_line() + if imgui.button("Clear Selection"): + self._slice_sel_start = -1 + self._slice_sel_end = -1 + + # Render existing slices (Tasks 3.4) + to_remove = -1 + for idx, slc in enumerate(self.ui_editing_slices_file.custom_slices): + imgui.push_id(f"slc_row_{idx}") + imgui.text(f"Slice {idx+1}: {slc['start_line']}-{slc['end_line']}") + imgui.same_line() + + imgui.set_next_item_width(100) + changed_tag, new_tag = imgui.input_text("Tag", slc.get('tag', '')) + if changed_tag: slc['tag'] = new_tag + + imgui.same_line() + imgui.set_next_item_width(200) + changed_comm, new_comm = imgui.input_text("Comment", slc.get('comment', '')) + if changed_comm: slc['comment'] = new_comm + + imgui.same_line() + if imgui.button("Remove"): + to_remove = idx + imgui.pop_id() + if to_remove != -1: + self.ui_editing_slices_file.custom_slices.pop(to_remove) + imgui.separator() + + # Toolbar + if imgui.button("Copy"): + imgui.set_clipboard_text(self.text_viewer_content) + imgui.same_line() + _, self.text_viewer_wrap = imgui.checkbox("Word Wrap", self.text_viewer_wrap) + imgui.separator() + + renderer = markdown_helper.get_renderer() + tv_type = getattr(self, "text_viewer_type", "text") + + if tv_type == 'markdown': + imgui.begin_child("tv_md_scroll", imgui.ImVec2(-1, -1), True) + markdown_helper.render(self.text_viewer_content, context_id='text_viewer') + imgui.end_child() + elif self.ui_editing_slices_file is not None: + # Manual renderer for slice editing (Tasks 3.1, 3.2, 3.3) + imgui.begin_child("slice_editor_content", imgui.ImVec2(-1, -1), True) + lines = self.text_viewer_content.splitlines() + draw_list = imgui.get_window_draw_list() + + for i, line_text in enumerate(lines): + line_num = i + 1 + pos = imgui.get_cursor_screen_pos() + line_height = imgui.get_text_line_height() + + # Check if part of any slice (Task 3.2) + is_sliced = False + for slc in self.ui_editing_slices_file.custom_slices: + if slc['start_line'] <= line_num <= slc['end_line']: + is_sliced = True + break + + if is_sliced: + # Orange alpha 0.2 + draw_list.add_rect_filled(pos, imgui.ImVec2(pos.x + imgui.get_content_region_avail().x, pos.y + line_height), imgui.get_color_u32(vec4(255, 165, 0, 0.2))) + + # Selection highlight (Task 3.3) + if self._slice_sel_start != -1 and self._slice_sel_end != -1: + s = min(self._slice_sel_start, self._slice_sel_end) + e = max(self._slice_sel_start, self._slice_sel_end) + if s <= line_num <= e: + draw_list.add_rect_filled(pos, imgui.ImVec2(pos.x + imgui.get_content_region_avail().x, pos.y + line_height), imgui.get_color_u32(vec4(100, 100, 255, 0.3))) + + imgui.selectable(f"{line_num:4} | {line_text}##ln{line_num}", False) + if imgui.is_item_clicked(): + self._slice_sel_start = line_num + self._slice_sel_end = line_num + if imgui.is_item_hovered() and imgui.is_mouse_down(0): + self._slice_sel_end = line_num + imgui.end_child() + elif tv_type in renderer._lang_map: + if self._text_viewer_editor is None: + self._text_viewer_editor = ced.TextEditor() + self._text_viewer_editor.set_read_only_enabled(True) + self._text_viewer_editor.set_show_line_numbers_enabled(True) + + # Sync text and language + lang_id = renderer._lang_map.get(tv_type, ced.TextEditor.LanguageDefinitionId.none) + if self._text_viewer_editor.get_text().strip() != self.text_viewer_content.strip(): + self._text_viewer_editor.set_text(self.text_viewer_content) + self._text_viewer_editor.set_language_definition(lang_id) + + self._text_viewer_editor.render('##tv_editor', a_size=imgui.ImVec2(-1, -1)) + else: + if self.text_viewer_wrap: + imgui.begin_child("tv_wrap", imgui.ImVec2(-1, -1), False) + imgui.push_text_wrap_pos(imgui.get_content_region_avail().x) + imgui.text(self.text_viewer_content) + imgui.pop_text_wrap_pos() + imgui.end_child() + else: + imgui.input_text_multiline("##tv_c", self.text_viewer_content, imgui.ImVec2(-1, -1), imgui.InputTextFlags_.read_only) + imgui.end() + #endregion: Cycle Detected Popup + + #region: Inject File Modal + if getattr(self, "show_inject_modal", False): + imgui.open_popup("Inject File") + self.show_inject_modal = False + + if imgui.begin_popup_modal("Inject File", None, imgui.WindowFlags_.always_auto_resize)[0]: + files = self.project.get('files', {}).get('paths', []) + imgui.text("Select File to Inject:") + imgui.begin_child("inject_file_list", imgui.ImVec2(0, 200), True) + for f_path in files: + is_selected = (self._inject_file_path == f_path) + if imgui.selectable(f_path, is_selected)[0]: + self._inject_file_path = f_path + self.controller._update_inject_preview() + imgui.end_child() + imgui.separator() + if imgui.radio_button("Skeleton", self._inject_mode == "skeleton"): + self._inject_mode = "skeleton" + self.controller._update_inject_preview() + imgui.same_line() + if imgui.radio_button("Full", self._inject_mode == "full"): + self._inject_mode = "full" + self.controller._update_inject_preview() + imgui.separator() + imgui.text("Preview:") + imgui.begin_child("inject_preview_area", imgui.ImVec2(600, 300), True) + imgui.text_unformatted(self._inject_preview) + imgui.end_child() + imgui.separator() + if imgui.button("Inject", imgui.ImVec2(120, 0)): + formatted = f"## File: {self._inject_file_path}\n```python\n{self._inject_preview}\n```\n" + with self._disc_entries_lock: + self.disc_entries.append({ + "role": "Context", + "content": formatted, + "collapsed": True, + "ts": project_manager.now_ts() + }) + self._scroll_disc_to_bottom = True + imgui.close_current_popup() + imgui.same_line() + if imgui.button("Cancel", imgui.ImVec2(120, 0)): + imgui.close_current_popup() + imgui.end_popup() + #endregion: Inject File Modal + + self._render_ast_inspector_modal() + return + def _gui_func(self) -> None: self._render_custom_title_bar() self._render_shader_live_editor() @@ -835,793 +1621,8 @@ class App: imgui.push_style_color(imgui.Col_.window_bg, vec4(50, 40, 20)) pushed_prior_tint = True - #region: Absurd Try Scope try: - self.perf_monitor.start_frame() - self._autofocus_response_tab = self.controller._autofocus_response_tab - - #region: Process GUI task queue - # DEBUG: Check if tasks exist before processing - if hasattr(self, 'controller') and hasattr(self.controller, '_pending_gui_tasks'): - pending_count = len(self.controller._pending_gui_tasks) - if pending_count > 0: - sys.stderr.write(f"[DEBUG gui_2] _gui_func: found {pending_count} pending tasks\n") - sys.stderr.flush() - self._process_pending_gui_tasks() - self._process_pending_history_adds() - if self.controller._process_pending_tool_calls(): - self._tool_log_dirty = True - #endregion: Process GUI task queue - - self._render_track_proposal_modal() - self._render_patch_modal() - self._render_base_prompt_diff_modal() - self._render_save_preset_modal() - self._render_save_workspace_profile_modal() - self._render_add_context_files_modal() - self._render_preset_manager_window() - self._render_tool_preset_manager_window() - self._render_persona_editor_window() - - # Auto-save (every 60s) - now = time.time() - if now - self._last_autosave >= self._autosave_interval: - self._last_autosave = now - try: - self._flush_to_project() - self._flush_to_config() - models.save_config(self.config) - except Exception: - pass # silent — don't disrupt the GUI loop - # Sync pending comms - with self._pending_comms_lock: - if self._pending_comms: - if self.ui_auto_scroll_comms: - self._scroll_comms_to_bottom = True - self._comms_log_dirty = True - for c in self._pending_comms: - self._comms_log.append(c) - self._pending_comms.clear() - - if self.ui_focus_agent != self._last_ui_focus_agent: - self._comms_log_dirty = True - self._tool_log_dirty = True - self._last_ui_focus_agent = self.ui_focus_agent - - if self._comms_log_dirty: - if self.is_viewing_prior_session: - self._comms_log_cache = self.prior_session_entries - else: - log_raw = list(self._comms_log) - if self.ui_focus_agent: - self._comms_log_cache = [e for e in log_raw if e.get("source_tier", "").startswith(self.ui_focus_agent)] - else: - self._comms_log_cache = log_raw - self._comms_log_dirty = False - - if self._tool_log_dirty: - if self.is_viewing_prior_session: - self._tool_log_cache = self.prior_tool_calls - else: - log_raw = list(self._tool_log) - if self.ui_focus_agent: - self._tool_log_cache = [e for e in log_raw if e.get("source_tier", "").startswith(self.ui_focus_agent)] - else: - self._tool_log_cache = log_raw - self._tool_log_dirty = False - - #region: Project Settings - if self.show_windows.get("Project Settings", False): - with imscope.window("Project Settings", self.show_windows["Project Settings"]) as (exp, opened): - self.show_windows["Project Settings"] = bool(opened) - if exp and imscope.tab_bar('context_hub_tabs'): - if imscope.tab_item('Projects'): self._render_projects_panel() - if imscope.tab_item('Paths'): self._render_paths_panel() - #endregion: Project Settings - - #region: Files & Media window - if self.show_windows.get("Files & Media", False): - exp, opened = imgui.begin("Files & Media", self.show_windows["Files & Media"]) - self.show_windows["Files & Media"] = bool(opened) - if opened: - if exp: - avail = imgui.get_content_region_avail().y - if not hasattr(self, 'files_screenshots_split'): - self.files_screenshots_split = 0.65 - split_y = int(avail * self.files_screenshots_split) - if imgui.collapsing_header("Files", imgui.TreeNodeFlags_.default_open): - imgui.begin_child("Files_child", imgui.ImVec2(-1, split_y), True) - if not hasattr(self, 'files_last_selected'): - self.files_last_selected = -1 - if imgui.begin_table("files_table", 5, imgui.TableFlags_.resizable | imgui.TableFlags_.borders): - imgui.table_setup_column("", imgui.TableColumnFlags_.width_fixed, 20) - imgui.table_setup_column("Path", imgui.TableColumnFlags_.width_stretch) - imgui.table_setup_column("Agg", imgui.TableColumnFlags_.width_fixed, 0) - imgui.table_setup_column("Full", imgui.TableColumnFlags_.width_fixed, 0) - imgui.table_setup_column("Cache", imgui.TableColumnFlags_.width_fixed, 0) - imgui.table_headers_row() - self.files.sort(key=lambda f: f.path.lower() if hasattr(f, 'path') else str(f).lower()) - for i, f_item in enumerate(self.files): - imgui.table_next_row() - imgui.table_set_column_index(0) - clicked, f_item.selected = imgui.checkbox(f"##{i}", f_item.selected) - if clicked: - if (imgui.is_key_down(imgui.Key.left_shift) or imgui.is_key_down(imgui.Key.right_shift)) and self.files_last_selected >= 0: - start_i = min(self.files_last_selected, i) - end_i = max(self.files_last_selected, i) - for j in range(start_i, end_i + 1): - self.files[j].selected = True - self.files_last_selected = i - imgui.table_set_column_index(1) - imgui.text(f_item.path if hasattr(f_item, 'path') else str(f_item)) - imgui.table_set_column_index(2) - if f_item.auto_aggregate: - imgui.text_colored(imgui.ImVec4(0.3, 0.8, 1, 1), "A") - else: - imgui.text_disabled(" ") - imgui.same_line(spacing=1) - if imgui.invisible_button(f"agg{i}", imgui.ImVec2(15, 15)): - f_item.auto_aggregate = not f_item.auto_aggregate - if f_item.auto_aggregate: - f_item.force_full = False - imgui.table_set_column_index(3) - if f_item.force_full: - imgui.text_colored(imgui.ImVec4(1, 0.6, 0.3, 1), "F") - else: - imgui.text_disabled(" ") - imgui.same_line(spacing=1) - if imgui.invisible_button(f"full{i}", imgui.ImVec2(15, 15)): - f_item.force_full = not f_item.force_full - if f_item.force_full: - f_item.auto_aggregate = False - imgui.table_set_column_index(4) - fpath = f_item.path if hasattr(f_item, 'path') else str(f_item) - is_cached = any(fpath in c for c in getattr(self, '_cached_files', [])) - if is_cached: - imgui.text_colored(imgui.ImVec4(0, 1, 0, 1), "Y") - else: - imgui.text_colored(imgui.ImVec4(0.5, 0.5, 0.5, 1), "-") - imgui.end_table() - if imgui.button("Add Files##addf"): - r = hide_tk_root() - paths = filedialog.askopenfilenames() - r.destroy() - for p in paths: - if p not in [f.path if hasattr(f, 'path') else f for f in self.files]: - self.files.append(models.FileItem(path=p)) - imgui.same_line() - if imgui.button("Sel All##selall"): - for f in self.files: - f.selected = True - imgui.same_line() - if imgui.button("Unsel##unselall"): - for f in self.files: - f.selected = False - imgui.same_line() - if imgui.button("None##nonesel"): - for f in self.files: - if f.selected: - f.auto_aggregate = False - f.force_full = False - imgui.same_line() - if imgui.button("Agg##aggsel"): - for f in self.files: - if f.selected: - f.auto_aggregate = True - f.force_full = False - imgui.same_line() - if imgui.button("Full##fullsel"): - for f in self.files: - if f.selected: - f.force_full = True - f.auto_aggregate = False - imgui.same_line() - if imgui.button("Del##dels"): - self.files = [f for f in self.files if not f.selected] - imgui.end_child() - imgui.separator() - if imgui.collapsing_header("Screenshots", imgui.TreeNodeFlags_.default_open): - imgui.begin_child("Shots_child", imgui.ImVec2(-1, -1), True) - for i, s in enumerate(self.screenshots): - if imgui.button(f"x##s{i}"): - self.screenshots.pop(i) - break - imgui.same_line() - imgui.text(s) - if imgui.button("Add Screenshots##adds"): - r = hide_tk_root() - paths = filedialog.askopenfilenames(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) - imgui.end_child() - imgui.end() - #endregion: Files & Media window - - #region: AI Settings - if self.show_windows.get("AI Settings", False): - with imscope.window("AI Settings", self.show_windows["AI Settings"]) as (exp, opened): - 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() - if imgui.collapsing_header("RAG Settings"): - self._render_rag_panel() - self._render_agent_tools_panel() - - 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() - if self.show_windows.get("MMA Dashboard", False): - exp, opened = imgui.begin("MMA Dashboard", self.show_windows["MMA Dashboard"]) - self.show_windows["MMA Dashboard"] = bool(opened) - if exp: - if self.perf_profiling_enabled: self.perf_monitor.start_component("_render_mma_dashboard") - self._render_mma_dashboard() - if self.perf_profiling_enabled: self.perf_monitor.end_component("_render_mma_dashboard") - imgui.end() - #endregion: AI Settings - - #region: Seprate Task Dag to Tier 4 - if self.ui_separate_task_dag and self.show_windows.get("Task DAG", False): - exp, opened = imgui.begin("Task DAG", self.show_windows["Task DAG"]) - self.show_windows["Task DAG"] = bool(opened) - if exp: - self._render_task_dag_panel() - imgui.end() - - if self.ui_separate_tier1 and self.show_windows.get("Tier 1: Strategy", False): - exp, opened = imgui.begin("Tier 1: Strategy", self.show_windows["Tier 1: Strategy"]) - self.show_windows["Tier 1: Strategy"] = bool(opened) - if exp: - self._render_tier_stream_panel("Tier 1", "Tier 1") - imgui.end() - - if self.ui_separate_tier2 and self.show_windows.get("Tier 2: Tech Lead", False): - exp, opened = imgui.begin("Tier 2: Tech Lead", self.show_windows["Tier 2: Tech Lead"]) - self.show_windows["Tier 2: Tech Lead"] = bool(opened) - if exp: - self._render_tier_stream_panel("Tier 2", "Tier 2 (Tech Lead)") - imgui.end() - - if self.ui_separate_tier3 and self.show_windows.get("Tier 3: Workers", False): - exp, opened = imgui.begin("Tier 3: Workers", self.show_windows["Tier 3: Workers"]) - self.show_windows["Tier 3: Workers"] = bool(opened) - if exp: - self._render_tier_stream_panel("Tier 3", None) - imgui.end() - - if self.ui_separate_tier4 and self.show_windows.get("Tier 4: QA", False): - exp, opened = imgui.begin("Tier 4: QA", self.show_windows["Tier 4: QA"]) - self.show_windows["Tier 4: QA"] = bool(opened) - if exp: - self._render_tier_stream_panel("Tier 4", "Tier 4 (QA)") - imgui.end() - #endregion: Separate Task Dag to Tier 4 - - if self.show_windows.get("Theme", False): - self._render_theme_panel() - - #region: Discussion Hub - if self.show_windows.get("Discussion Hub", False): - exp, opened = imgui.begin("Discussion Hub", self.show_windows["Discussion Hub"]) - self.show_windows["Discussion Hub"] = bool(opened) - if exp: - if imgui.begin_tab_bar("discussion_hub_tabs"): - if imgui.begin_tab_item("Discussion")[0]: - self._render_discussion_tab() - imgui.end_tab_item() - if imgui.begin_tab_item("Context Composition")[0]: - self._render_context_composition_panel() - imgui.end_tab_item() - if imgui.begin_tab_item("Snapshot")[0]: - self._render_snapshot_tab() - imgui.end_tab_item() - if imgui.begin_tab_item("Takes")[0]: - self._render_takes_panel() - imgui.end_tab_item() - imgui.end_tab_bar() - imgui.end() - #endregion: Discussion Hub - - #region: Operations Hub - if self.show_windows.get("Operations Hub", False): - exp, opened = imgui.begin("Operations Hub", self.show_windows["Operations Hub"]) - self.show_windows["Operations Hub"] = bool(opened) - if exp: - imgui.push_style_var(imgui.StyleVar_.item_spacing, imgui.ImVec2(10, 4)) - ch1, self.ui_separate_tool_calls_panel = imgui.checkbox("Pop Out Tool Calls", self.ui_separate_tool_calls_panel) - if ch1: self.show_windows["Tool Calls"] = self.ui_separate_tool_calls_panel - imgui.same_line() - ch2, self.ui_separate_usage_analytics = imgui.checkbox("Pop Out Usage Analytics", self.ui_separate_usage_analytics) - if ch2: self.show_windows["Usage Analytics"] = self.ui_separate_usage_analytics - imgui.same_line() - ch3, self.ui_separate_external_tools = imgui.checkbox('Pop Out External Tools', self.ui_separate_external_tools) - if ch3: self.show_windows['External Tools'] = self.ui_separate_external_tools - imgui.pop_style_var() - - show_tc_tab = not self.ui_separate_tool_calls_panel - show_usage_tab = not self.ui_separate_usage_analytics - - if imgui.begin_tab_bar("ops_tabs"): - if imgui.begin_tab_item("Comms History")[0]: - self._render_comms_history_panel() - imgui.end_tab_item() - if show_tc_tab: - if imgui.begin_tab_item("Tool Calls")[0]: - self._render_tool_calls_panel() - imgui.end_tab_item() - if show_usage_tab: - if imgui.begin_tab_item("Usage Analytics")[0]: - self._render_usage_analytics_panel() - imgui.end_tab_item() - if not self.ui_separate_external_tools: - if imgui.begin_tab_item("External Tools")[0]: - self._render_external_tools_panel() - imgui.separator() - imgui.text("") - try: - self._render_external_editor_panel() - except Exception as e: - imgui.text_colored(vec4(1, 0.3, 0.3, 1), f"Error: {str(e)}") - imgui.end_tab_item() - if imgui.begin_tab_item("Workspace Layouts")[0]: - imgui.text("Experimental: Auto-switch layout by Tier") - ch, self.controller.ui_auto_switch_layout = imgui.checkbox("Enable Auto-Switch", self.controller.ui_auto_switch_layout) - if self.controller.ui_auto_switch_layout: - imgui.separator() - imgui.text("Tier Bindings (select profile for each tier)") - profiles = [""] + [p.name for p in self.controller.workspace_profiles.values()] - for t in ["Tier 1", "Tier 2", "Tier 3", "Tier 4"]: - curr = self.controller.ui_tier_layout_bindings.get(t, "") - idx = profiles.index(curr) if curr in profiles else 0 - ch_combo, new_idx = imgui.combo(t, idx, profiles) - if ch_combo: - self.controller.ui_tier_layout_bindings[t] = profiles[new_idx] - imgui.end_tab_item() - imgui.end_tab_bar() - imgui.end() - #endregion: Operations Hub - - #region: Separate Message, Response, Tool Calls, External Tools - if self.ui_separate_message_panel and self.show_windows.get("Message", False): - exp, opened = imgui.begin("Message", self.show_windows["Message"]) - self.show_windows["Message"] = bool(opened) - if exp: - self._render_message_panel() - imgui.end() - - if self.ui_separate_response_panel and self.show_windows.get("Response", False): - exp, opened = imgui.begin("Response", self.show_windows["Response"]) - self.show_windows["Response"] = bool(opened) - if exp: - self._render_response_panel() - imgui.end() - - if self.ui_separate_tool_calls_panel and self.show_windows.get("Tool Calls", False): - exp, opened = imgui.begin("Tool Calls", self.show_windows["Tool Calls"]) - self.show_windows["Tool Calls"] = bool(opened) - if exp: - self._render_tool_calls_panel() - imgui.end() - - if self.ui_separate_external_tools and self.show_windows.get('External Tools', False): - exp, opened = imgui.begin('External Tools', self.show_windows['External Tools']) - self.show_windows['External Tools'] = bool(opened) - if exp: - self._render_external_tools_panel() - imgui.end() - - if self.show_windows.get("Log Management", False): - if self.perf_profiling_enabled: self.perf_monitor.start_component("_render_log_management") - self._render_log_management() - if self.perf_profiling_enabled: self.perf_monitor.end_component("_render_log_management") - #endregion: Separate Message, Response, Tool Calls, External Tools - - if self.show_windows.get("Diagnostics", False): - self._render_diagnostics_panel() - - self.perf_monitor.end_frame() - - # Modals / Popups - - with self._pending_dialog_lock: - dlg = self._pending_dialog - if dlg: - if not self._pending_dialog_open: - imgui.open_popup("Approve PowerShell Command") - self._pending_dialog_open = True - else: - self._pending_dialog_open = False - - if imgui.begin_popup_modal("Approve PowerShell Command", None, imgui.WindowFlags_.always_auto_resize)[0]: - if not dlg: - imgui.close_current_popup() - else: - imgui.text("The AI wants to run the following PowerShell script:") - imgui.text_colored(vec4(200, 200, 100), f"base_dir: {dlg._base_dir}") - imgui.separator() - # Checkbox to toggle full preview inside modal - _, self.show_text_viewer = imgui.checkbox("Show Full Preview", self.show_text_viewer) - if self.show_text_viewer: - imgui.begin_child("preview_child", imgui.ImVec2(600, 300), True) - imgui.text_unformatted(dlg._script) - imgui.end_child() - else: - ch, dlg._script = imgui.input_text_multiline("##confirm_script", dlg._script, imgui.ImVec2(-1, 200)) - imgui.separator() - if imgui.button("Approve & Run", imgui.ImVec2(120, 0)): - with dlg._condition: - dlg._approved = True - dlg._done = True - dlg._condition.notify_all() - with self._pending_dialog_lock: - self._pending_dialog = None - imgui.close_current_popup() - imgui.same_line() - if imgui.button("Reject", imgui.ImVec2(120, 0)): - with dlg._condition: - dlg._approved = False - dlg._done = True - dlg._condition.notify_all() - with self._pending_dialog_lock: - self._pending_dialog = None - imgui.close_current_popup() - imgui.end_popup() - - if self._pending_ask_dialog: - if not self._ask_dialog_open: - imgui.open_popup("Approve Tool Execution") - self._ask_dialog_open = True - else: - self._ask_dialog_open = False - - if imgui.begin_popup_modal("Approve Tool Execution", None, imgui.WindowFlags_.always_auto_resize)[0]: - if not self._pending_ask_dialog or self._ask_tool_data is None: - imgui.close_current_popup() - else: - tool_name = self._ask_tool_data.get("tool", "unknown") - tool_args = self._ask_tool_data.get("args", {}) - imgui.text("The AI wants to execute a tool:") - imgui.text_colored(vec4(200, 200, 100), f"Tool: {tool_name}") - imgui.separator() - imgui.text("Arguments:") - imgui.begin_child("ask_args_child", imgui.ImVec2(400, 200), True) - imgui.text_unformatted(json.dumps(tool_args, indent=2)) - imgui.end_child() - imgui.separator() - if imgui.button("Approve", imgui.ImVec2(120, 0)): - self._handle_approve_ask() - imgui.close_current_popup() - imgui.same_line() - if imgui.button("Deny", imgui.ImVec2(120, 0)): - self._handle_reject_ask() - imgui.close_current_popup() - imgui.end_popup() - - #region: MMA Step Approval Modal - if self._pending_mma_approvals: - if not self._mma_approval_open: - imgui.open_popup("MMA Step Approval") - self._mma_approval_open = True - self._mma_approval_edit_mode = False - self._mma_approval_payload = self._pending_mma_approvals[0].get("payload", "") - else: - self._mma_approval_open = False - if imgui.begin_popup_modal("MMA Step Approval", None, imgui.WindowFlags_.always_auto_resize)[0]: - if not self._pending_mma_approvals: - imgui.close_current_popup() - else: - ticket_id = self._pending_mma_approvals[0].get("ticket_id", "??") - imgui.text(f"Ticket {ticket_id} is waiting for tool execution approval.") - imgui.separator() - if self._mma_approval_edit_mode: - imgui.text("Edit Raw Payload (Manual Memory Mutation):") - _, self._mma_approval_payload = imgui.input_text_multiline("##mma_payload", self._mma_approval_payload, imgui.ImVec2(600, 400)) - else: - imgui.text("Proposed Tool Call:") - imgui.begin_child("mma_preview", imgui.ImVec2(600, 300), True) - imgui.text_unformatted(str(self._pending_mma_approvals[0].get("payload", ""))) - imgui.end_child() - imgui.separator() - if imgui.button("Approve", imgui.ImVec2(120, 0)): - self._handle_mma_respond(approved=True, payload=self._mma_approval_payload) - imgui.close_current_popup() - imgui.same_line() - if imgui.button("Edit Payload" if not self._mma_approval_edit_mode else "Show Original", imgui.ImVec2(120, 0)): - self._mma_approval_edit_mode = not self._mma_approval_edit_mode - imgui.same_line() - if imgui.button("Abort Ticket", imgui.ImVec2(120, 0)): - self._handle_mma_respond(approved=False) - imgui.close_current_popup() - imgui.end_popup() - #endregion: MMA Step Approval Modal - - #region: MMA Spawn Approval Modal - if self._pending_mma_spawns: - if not self._mma_spawn_open: - imgui.open_popup("MMA Spawn Approval") - self._mma_spawn_open = True - self._mma_spawn_edit_mode = False - self._mma_spawn_prompt = self._pending_mma_spawns[0].get("prompt", "") - self._mma_spawn_context = self._pending_mma_spawns[0].get("context_md", "") - else: - self._mma_spawn_open = False - - if imgui.begin_popup_modal("MMA Spawn Approval", None, imgui.WindowFlags_.always_auto_resize)[0]: - if not self._pending_mma_spawns: - imgui.close_current_popup() - else: - role = self._pending_mma_spawns[0].get("role", "??") - ticket_id = self._pending_mma_spawns[0].get("ticket_id", "??") - imgui.text(f"Spawning {role} for Ticket {ticket_id}") - imgui.separator() - if self._mma_spawn_edit_mode: - imgui.text("Edit Prompt:") - _, self._mma_spawn_prompt = imgui.input_text_multiline("##spawn_prompt", self._mma_spawn_prompt, imgui.ImVec2(800, 200)) - imgui.text("Edit Context MD:") - _, self._mma_spawn_context = imgui.input_text_multiline("##spawn_context", self._mma_spawn_context, imgui.ImVec2(800, 300)) - else: - imgui.text("Proposed Prompt:") - imgui.begin_child("spawn_prompt_preview", imgui.ImVec2(800, 150), True) - imgui.text_unformatted(self._mma_spawn_prompt) - imgui.end_child() - imgui.text("Proposed Context MD:") - imgui.begin_child("spawn_context_preview", imgui.ImVec2(800, 250), True) - imgui.text_unformatted(self._mma_spawn_context) - imgui.end_child() - imgui.separator() - if imgui.button("Approve", imgui.ImVec2(120, 0)): - self._handle_mma_respond(approved=True, prompt=self._mma_spawn_prompt, context_md=self._mma_spawn_context) - imgui.close_current_popup() - imgui.same_line() - if imgui.button("Edit Mode" if not self._mma_spawn_edit_mode else "Preview Mode", imgui.ImVec2(120, 0)): - self._mma_spawn_edit_mode = not self._mma_spawn_edit_mode - imgui.same_line() - if imgui.button("Abort", imgui.ImVec2(120, 0)): - self._handle_mma_respond(approved=False, abort=True) - imgui.close_current_popup() - imgui.end_popup() - #endregion: MMA Spawn Approval Modal - - #region: Cycle Detected Popup - if imgui.begin_popup_modal("Cycle Detected!", None, imgui.WindowFlags_.always_auto_resize)[0]: - imgui.text_colored(imgui.ImVec4(1, 0.3, 0.3, 1), "The dependency graph contains a cycle!") - imgui.text("Please remove the circular dependency.") - if imgui.button("OK"): - imgui.close_current_popup() - imgui.end_popup() - if self.show_script_output: - if self._trigger_script_blink: - self._trigger_script_blink = False - self._is_script_blinking = True - self._script_blink_start_time = time.time() - try: - imgui.set_window_focus("Last Script Output") # type: ignore[call-arg] - except Exception: - pass - if self._is_script_blinking: - elapsed = time.time() - self._script_blink_start_time - if elapsed > 1.5: - self._is_script_blinking = False - else: - val = math.sin(elapsed * 8 * math.pi) - alpha = 60/255 if val > 0 else 0 - imgui.push_style_color(imgui.Col_.frame_bg, vec4(0, 100, 255, alpha)) - imgui.push_style_color(imgui.Col_.child_bg, vec4(0, 100, 255, alpha)) - imgui.set_next_window_size(imgui.ImVec2(800, 600), imgui.Cond_.first_use_ever) - expanded, opened = imgui.begin("Last Script Output", self.show_script_output) - self.show_script_output = bool(opened) - if expanded: - imgui.text("Script:") - imgui.same_line() - self._render_text_viewer("Last Script", self.ui_last_script_text) - if self.ui_word_wrap: - imgui.begin_child("lso_s_wrap", imgui.ImVec2(-1, 200), True) - imgui.push_text_wrap_pos(imgui.get_content_region_avail().x) - imgui.text(self.ui_last_script_text) - imgui.pop_text_wrap_pos() - imgui.end_child() - else: - imgui.input_text_multiline("##lso_s", self.ui_last_script_text, imgui.ImVec2(-1, 200), imgui.InputTextFlags_.read_only) - imgui.separator() - imgui.text("Output:") - imgui.same_line() - self._render_text_viewer("Last Output", self.ui_last_script_output) - if self.ui_word_wrap: - imgui.begin_child("lso_o_wrap", imgui.ImVec2(-1, -1), True) - imgui.push_text_wrap_pos(imgui.get_content_region_avail().x) - imgui.text(self.ui_last_script_output) - imgui.pop_text_wrap_pos() - imgui.end_child() - else: - imgui.input_text_multiline("##lso_o", self.ui_last_script_output, imgui.ImVec2(-1, -1), imgui.InputTextFlags_.read_only) - if self._is_script_blinking: - imgui.pop_style_color(2) - imgui.end() - if self.show_text_viewer: - imgui.set_next_window_size(imgui.ImVec2(900, 700), imgui.Cond_.first_use_ever) - expanded, opened = imgui.begin(f"Text Viewer - {self.text_viewer_title}", self.show_text_viewer) - self.show_text_viewer = bool(opened) - if not opened: - self.ui_editing_slices_file = None - self._slice_sel_start = -1 - self._slice_sel_end = -1 - - if expanded: - if self.ui_editing_slices_file is not None: - imgui.text_colored(C_IN, "Slice Management (Click-drag lines to select range)") - if imgui.button("Add Selection as Slice"): - if self._slice_sel_start != -1 and self._slice_sel_end != -1: - s_line = min(self._slice_sel_start, self._slice_sel_end) - e_line = max(self._slice_sel_start, self._slice_sel_end) - from src.fuzzy_anchor import FuzzyAnchor - slice_data = FuzzyAnchor.create_slice(self.text_viewer_content, s_line, e_line) - slice_data['tag'] = "" - slice_data['comment'] = "" - self.ui_editing_slices_file.custom_slices.append(slice_data) - self._slice_sel_start = -1 - self._slice_sel_end = -1 - imgui.same_line() - if imgui.button("Clear Selection"): - self._slice_sel_start = -1 - self._slice_sel_end = -1 - - # Render existing slices (Tasks 3.4) - to_remove = -1 - for idx, slc in enumerate(self.ui_editing_slices_file.custom_slices): - imgui.push_id(f"slc_row_{idx}") - imgui.text(f"Slice {idx+1}: {slc['start_line']}-{slc['end_line']}") - imgui.same_line() - - imgui.set_next_item_width(100) - changed_tag, new_tag = imgui.input_text("Tag", slc.get('tag', '')) - if changed_tag: slc['tag'] = new_tag - - imgui.same_line() - imgui.set_next_item_width(200) - changed_comm, new_comm = imgui.input_text("Comment", slc.get('comment', '')) - if changed_comm: slc['comment'] = new_comm - - imgui.same_line() - if imgui.button("Remove"): - to_remove = idx - imgui.pop_id() - if to_remove != -1: - self.ui_editing_slices_file.custom_slices.pop(to_remove) - imgui.separator() - - # Toolbar - if imgui.button("Copy"): - imgui.set_clipboard_text(self.text_viewer_content) - imgui.same_line() - _, self.text_viewer_wrap = imgui.checkbox("Word Wrap", self.text_viewer_wrap) - imgui.separator() - - renderer = markdown_helper.get_renderer() - tv_type = getattr(self, "text_viewer_type", "text") - - if tv_type == 'markdown': - imgui.begin_child("tv_md_scroll", imgui.ImVec2(-1, -1), True) - markdown_helper.render(self.text_viewer_content, context_id='text_viewer') - imgui.end_child() - elif self.ui_editing_slices_file is not None: - # Manual renderer for slice editing (Tasks 3.1, 3.2, 3.3) - imgui.begin_child("slice_editor_content", imgui.ImVec2(-1, -1), True) - lines = self.text_viewer_content.splitlines() - draw_list = imgui.get_window_draw_list() - - for i, line_text in enumerate(lines): - line_num = i + 1 - pos = imgui.get_cursor_screen_pos() - line_height = imgui.get_text_line_height() - - # Check if part of any slice (Task 3.2) - is_sliced = False - for slc in self.ui_editing_slices_file.custom_slices: - if slc['start_line'] <= line_num <= slc['end_line']: - is_sliced = True - break - - if is_sliced: - # Orange alpha 0.2 - draw_list.add_rect_filled(pos, imgui.ImVec2(pos.x + imgui.get_content_region_avail().x, pos.y + line_height), imgui.get_color_u32(vec4(255, 165, 0, 0.2))) - - # Selection highlight (Task 3.3) - if self._slice_sel_start != -1 and self._slice_sel_end != -1: - s = min(self._slice_sel_start, self._slice_sel_end) - e = max(self._slice_sel_start, self._slice_sel_end) - if s <= line_num <= e: - draw_list.add_rect_filled(pos, imgui.ImVec2(pos.x + imgui.get_content_region_avail().x, pos.y + line_height), imgui.get_color_u32(vec4(100, 100, 255, 0.3))) - - imgui.selectable(f"{line_num:4} | {line_text}##ln{line_num}", False) - if imgui.is_item_clicked(): - self._slice_sel_start = line_num - self._slice_sel_end = line_num - if imgui.is_item_hovered() and imgui.is_mouse_down(0): - self._slice_sel_end = line_num - imgui.end_child() - elif tv_type in renderer._lang_map: - if self._text_viewer_editor is None: - self._text_viewer_editor = ced.TextEditor() - self._text_viewer_editor.set_read_only_enabled(True) - self._text_viewer_editor.set_show_line_numbers_enabled(True) - - # Sync text and language - lang_id = renderer._lang_map.get(tv_type, ced.TextEditor.LanguageDefinitionId.none) - if self._text_viewer_editor.get_text().strip() != self.text_viewer_content.strip(): - self._text_viewer_editor.set_text(self.text_viewer_content) - self._text_viewer_editor.set_language_definition(lang_id) - - self._text_viewer_editor.render('##tv_editor', a_size=imgui.ImVec2(-1, -1)) - else: - if self.text_viewer_wrap: - imgui.begin_child("tv_wrap", imgui.ImVec2(-1, -1), False) - imgui.push_text_wrap_pos(imgui.get_content_region_avail().x) - imgui.text(self.text_viewer_content) - imgui.pop_text_wrap_pos() - imgui.end_child() - else: - imgui.input_text_multiline("##tv_c", self.text_viewer_content, imgui.ImVec2(-1, -1), imgui.InputTextFlags_.read_only) - imgui.end() - #endregion: Cycle Detected Popup - - #region: Inject File Modal - if getattr(self, "show_inject_modal", False): - imgui.open_popup("Inject File") - self.show_inject_modal = False - - if imgui.begin_popup_modal("Inject File", None, imgui.WindowFlags_.always_auto_resize)[0]: - files = self.project.get('files', {}).get('paths', []) - imgui.text("Select File to Inject:") - imgui.begin_child("inject_file_list", imgui.ImVec2(0, 200), True) - for f_path in files: - is_selected = (self._inject_file_path == f_path) - if imgui.selectable(f_path, is_selected)[0]: - self._inject_file_path = f_path - self.controller._update_inject_preview() - imgui.end_child() - imgui.separator() - if imgui.radio_button("Skeleton", self._inject_mode == "skeleton"): - self._inject_mode = "skeleton" - self.controller._update_inject_preview() - imgui.same_line() - if imgui.radio_button("Full", self._inject_mode == "full"): - self._inject_mode = "full" - self.controller._update_inject_preview() - imgui.separator() - imgui.text("Preview:") - imgui.begin_child("inject_preview_area", imgui.ImVec2(600, 300), True) - imgui.text_unformatted(self._inject_preview) - imgui.end_child() - imgui.separator() - if imgui.button("Inject", imgui.ImVec2(120, 0)): - formatted = f"## File: {self._inject_file_path}\n```python\n{self._inject_preview}\n```\n" - with self._disc_entries_lock: - self.disc_entries.append({ - "role": "Context", - "content": formatted, - "collapsed": True, - "ts": project_manager.now_ts() - }) - self._scroll_disc_to_bottom = True - imgui.close_current_popup() - imgui.same_line() - if imgui.button("Cancel", imgui.ImVec2(120, 0)): - imgui.close_current_popup() - imgui.end_popup() - #endregion: Inject File Modal - - self._render_ast_inspector_modal() - #endregion: Absurd Try Scope - + self._gui_func__abusrd_try_scope() except Exception as e: print(f"ERROR in _gui_func: {e}") traceback.print_exc() @@ -1632,6 +1633,7 @@ class App: self._handle_history_logic() if self.perf_profiling_enabled: self.perf_monitor.end_component("_gui_func") + return def _handle_history_logic(self) -> None: """