diff --git a/src/gui_2.py b/src/gui_2.py index d49df11..52d77bf 100644 --- a/src/gui_2.py +++ b/src/gui_2.py @@ -1625,197 +1625,78 @@ class App: with imscope.tab_item("Beads") as (exp, _): if exp: self._render_beads_tab() imgui.end_tab_bar() - - 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() + + def _render_text_viewer_window(self) -> None: + """Renders the standalone text/code/markdown viewer window.""" + if not self.show_text_viewer: return + 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("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 - 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 + if imgui.button("Clear Selection"): self._slice_sel_start = -1; self._slice_sel_end = -1 + 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("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) + 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() - - 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() - + 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': + with imscope.child("tv_md_scroll", -1, -1, True): markdown_helper.render(self.text_viewer_content, context_id='text_viewer') + elif self.ui_editing_slices_file is not None: + with imscope.child("slice_editor_content", -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) + line_num = i + 1; pos = imgui.get_cursor_screen_pos(); line_height = imgui.get_text_line_height() + is_sliced = any(slc['start_line'] <= line_num <= slc['end_line'] for slc in self.ui_editing_slices_file.custom_slices) + if is_sliced: 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))) 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))) - + s, e = min(self._slice_sel_start, self._slice_sel_end), 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) - + 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 + 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) + try: + self._text_viewer_editor.set_text(self.text_viewer_content) + if self.perf_profiling_enabled: self.perf_monitor.start_component("_render_text_viewer_ced") + self._text_viewer_editor.render(f"##ced_{self.text_viewer_title}", imgui.ImVec2(-1, -1)) + if self.perf_profiling_enabled: self.perf_monitor.end_component("_render_text_viewer_ced") + except Exception as e: imgui.text_colored(vec4(255, 100, 100), f"CED Error: {e}"); imgui.text_unformatted(self.text_viewer_content) + else: + with imscope.child("tv_scroll", -1, -1, True): + if self.text_viewer_wrap: imgui.push_text_wrap_pos(imgui.get_content_region_avail().x) + imgui.text_unformatted(self.text_viewer_content) + if self.text_viewer_wrap: imgui.pop_text_wrap_pos() + imgui.end() # 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): @@ -5307,16 +5188,7 @@ def hello(): imgui.end() if self.perf_profiling_enabled: self.perf_monitor.end_component("_render_theme_panel") - def _render_thinking_indicator(self) -> None: - is_thinking = self.ai_status in ['sending...', 'streaming...', 'running powershell...'] - if is_thinking: - val = math.sin(time.time() * 10 * math.pi) - alpha = 1.0 if val > 0 else 0.0 - c = vec4(255, 50, 50, alpha) if theme.is_nerv_active() else vec4(255, 100, 100, alpha) - imgui.text_colored(c, "THINKING..."); imgui.same_line() - - def _render_prior_session_view(self) -> None: - imgui.push_style_color(imgui.Col_.child_bg, vec4(50, 40, 20)) + def _render_prior_session_view(self) -> None: imgui.push_style_color(imgui.Col_.child_bg, vec4(50, 40, 20)) if imgui.button("Exit Prior Session"): self.controller.cb_exit_prior_session(); self._comms_log_dirty = True imgui.separator() with imscope.child("prior_scroll"):