diff --git a/src/gui_2.py b/src/gui_2.py index e99a3626..b571fff5 100644 --- a/src/gui_2.py +++ b/src/gui_2.py @@ -3603,7 +3603,7 @@ def render_ast_inspector_modal(app: App) -> None: if getattr(app, 'show_structural_editor_modal', False): imgui.open_popup('Structural File Editor') app.show_structural_editor_modal = False - + imgui.set_next_window_size(imgui.ImVec2(1400, 900), imgui.Cond_.first_use_ever) expanded, opened = imgui.begin_popup_modal('Structural File Editor', True, imgui.WindowFlags_.none) if opened: @@ -3613,19 +3613,19 @@ def render_ast_inspector_modal(app: App) -> None: else: f_item = app.ui_editing_slices_file f_path = f_item.path if hasattr(f_item, "path") else str(f_item) - + if f_path != getattr(app, '_cached_ast_file_path', None): outline = "" try: proj_dir = str(Path(app.controller.active_project_path).parent.resolve()) if getattr(app, 'controller', None) and app.controller.active_project_path else None mcp_client.configure([{"path": f_path}], [proj_dir] if proj_dir else None) - + if f_path.lower().endswith('.py'): outline = mcp_client.py_get_code_outline(f_path) elif f_path.lower().endswith(('.c', '.h')): outline = mcp_client.ts_c_get_code_outline(f_path) elif f_path.lower().endswith(('.cpp', '.hpp', '.cxx', '.cc')): outline = mcp_client.ts_cpp_get_code_outline(f_path) except Exception as e: outline = f"Error fetching outline: {e}" - + app._cached_ast_nodes = [] import re #TODO(Ed): Review local import pattern = re.compile(r'^(\s*)\[(.*?)\] (.*?) \(Lines (\d+)-(\d+)\)') @@ -3639,34 +3639,34 @@ def render_ast_inspector_modal(app: App) -> None: stack.append((indent, name)) full_path = '::'.join([s[1] for s in stack]) app._cached_ast_nodes.append({ - 'indent': indent, - 'kind': kind, - 'name': name, - 'full_path': full_path, + 'indent': indent, + 'kind': kind, + 'name': name, + 'full_path': full_path, 'start_line': int(start_ln), - 'end_line': int(end_ln) + 'end_line': int(end_ln) }) try: - content = mcp_client.read_file(f_path) + content = mcp_client.read_file(f_path) app._cached_ast_file_lines = content.splitlines() - app.text_viewer_content = content + app.text_viewer_content = content except Exception: app._cached_ast_file_lines = ["Error loading file content."] - app.text_viewer_content = "Error loading file content." - app._cached_ast_file_path = f_path - + app.text_viewer_content = "Error loading file content." + app._cached_ast_file_path = f_path + imgui.text(f"Editing Structure: {f_path}") imgui.separator() - - avail = imgui.get_content_region_avail() + + avail = imgui.get_content_region_avail() table_height = max(100.0, avail.y - imgui.get_frame_height_with_spacing() * 2 - 20) - + if imgui.begin_table('structure_dual_pane', 2, imgui.TableFlags_.resizable | imgui.TableFlags_.borders_inner_v, imgui.ImVec2(0, table_height)): - imgui.table_setup_column("AST & Slices", imgui.TableColumnFlags_.width_fixed, 400) + imgui.table_setup_column("AST & Slices", imgui.TableColumnFlags_.width_fixed, 400) imgui.table_setup_column("Content Preview", imgui.TableColumnFlags_.width_stretch) imgui.table_next_row() imgui.table_next_column() - + # --- LEFT COLUMN: AST Tree & Slice Management --- imgui.begin_child("ast_tree_scroll", imgui.ImVec2(0, 0), True) # if True: @@ -3700,7 +3700,7 @@ def render_ast_inspector_modal(app: App) -> None: # if do_align: imgui.same_line((avail_width - btn_width)) # else: imgui.same_line() # imgui.same_line((avail_width - btn_width) * 0.925) - + if not hasattr(f_item, 'ast_mask'): f_item.ast_mask = {} current_mode = f_item.ast_mask.get(full_path, 'hide') @@ -3721,12 +3721,15 @@ def render_ast_inspector_modal(app: App) -> None: s_line = min(app._slice_sel_start, app._slice_sel_end) e_line = max(app._slice_sel_start, app._slice_sel_end) from src.fuzzy_anchor import FuzzyAnchor - slice_data = FuzzyAnchor.create_slice(app.text_viewer_content, s_line, e_line) + slice_data = FuzzyAnchor.create_slice(app.text_viewer_content, s_line, e_line) slice_data['tag'] = ""; slice_data['comment'] = "" f_item.custom_slices.append(slice_data) - app._slice_sel_start = -1; app._slice_sel_end = -1 + app._slice_sel_start = -1 + app._slice_sel_end = -1 imgui.same_line() - if imgui.button("Clear Selection"): app._slice_sel_start = -1; app._slice_sel_end = -1 + if imgui.button("Clear Selection"): + app._slice_sel_start = -1 + app._slice_sel_end = -1 imgui.same_line() if imgui.button("Auto-Populate"): app._populate_auto_slices(f_item) @@ -3747,9 +3750,9 @@ def render_ast_inspector_modal(app: App) -> None: imgui.pop_id() if to_remove != -1: f_item.custom_slices.pop(to_remove) imgui.end_child() - + imgui.table_next_column() - + # --- RIGHT COLUMN: Content Preview with Highlights --- with imscope.child("ast_content_scroll", imgui.ImVec2(0, 0), True): if not getattr(app, '_cached_ast_file_lines', None): @@ -3758,10 +3761,10 @@ def render_ast_inspector_modal(app: App) -> None: draw_list = imgui.get_window_draw_list() for i, line_text in enumerate(app._cached_ast_file_lines): line_num = i + 1 - pos = imgui.get_cursor_screen_pos() + pos = imgui.get_cursor_screen_pos() line_height = imgui.get_text_line_height() avail_width = imgui.get_content_region_avail().x - + # 1. AST Highlight deepest_node = None for node in app._cached_ast_nodes: @@ -3769,31 +3772,29 @@ def render_ast_inspector_modal(app: App) -> None: if deepest_node is None or node['indent'] > deepest_node['indent']: deepest_node = node mode = 'hide' if deepest_node: mode = getattr(f_item, 'ast_mask', {}).get(deepest_node['full_path'], 'hide') - if mode == 'def': - draw_list.add_rect_filled(pos, imgui.ImVec2(pos.x + avail_width, pos.y + line_height), imgui.get_color_u32(theme.get_color("slice_auto", alpha=0.15))) - elif mode == 'sig': - draw_list.add_rect_filled(pos, imgui.ImVec2(pos.x + avail_width, pos.y + line_height), imgui.get_color_u32(theme.get_color("slice_selection", alpha=0.15))) + if mode == 'def': draw_list.add_rect_filled(pos, imgui.ImVec2(pos.x + avail_width, pos.y + line_height), imgui.get_color_u32(theme.get_color("slice_auto", alpha=0.15))) + elif mode == 'sig': draw_list.add_rect_filled(pos, imgui.ImVec2(pos.x + avail_width, pos.y + line_height), imgui.get_color_u32(theme.get_color("slice_selection", alpha=0.15))) elif deepest_node and deepest_node['full_path'] == getattr(app, '_hovered_ast_node', None): draw_list.add_rect_filled(pos, imgui.ImVec2(pos.x + avail_width, pos.y + line_height), imgui.get_color_u32(theme.get_color("status_warning", alpha=0.2))) - + # 2. Slice Highlight if hasattr(f_item, 'custom_slices'): is_auto = any(slc['start_line'] <= line_num <= slc['end_line'] for slc in f_item.custom_slices if slc.get('tag') == 'auto-ast') - is_man = any(slc['start_line'] <= line_num <= slc['end_line'] for slc in f_item.custom_slices if slc.get('tag') != 'auto-ast') + is_man = any(slc['start_line'] <= line_num <= slc['end_line'] for slc in f_item.custom_slices if slc.get('tag') != 'auto-ast') if is_man: draw_list.add_rect_filled(pos, imgui.ImVec2(pos.x + avail_width, pos.y + line_height), imgui.get_color_u32(theme.get_color("slice_manual", alpha=0.2))) elif is_auto and mode == 'hide': draw_list.add_rect_filled(pos, imgui.ImVec2(pos.x + avail_width, pos.y + line_height), imgui.get_color_u32(theme.get_color("slice_auto", alpha=0.1))) - + # 3. Active Selection Highlight if getattr(app, '_slice_sel_start', -1) != -1 and getattr(app, '_slice_sel_end', -1) != -1: s, e = min(app._slice_sel_start, app._slice_sel_end), max(app._slice_sel_start, app._slice_sel_end) if s <= line_num <= e: draw_list.add_rect_filled(pos, imgui.ImVec2(pos.x + avail_width, pos.y + line_height), imgui.get_color_u32(theme.get_color("slice_selection", alpha=0.3))) - + imgui.selectable(f"{line_num:4} | {line_text}##ln{line_num}", False) if imgui.is_item_clicked(): app._slice_sel_start = line_num; app._slice_sel_end = line_num if imgui.is_item_hovered(imgui.HoveredFlags_.allow_when_blocked_by_active_item) and imgui.is_mouse_down(0): app._slice_sel_end = line_num - + imgui.end_table() - + imgui.separator() if imgui.button("Close", imgui.ImVec2(120, 0)): app.ui_editing_slices_file = None @@ -3806,11 +3807,9 @@ def render_ast_inspector_modal(app: App) -> None: app.ui_inspecting_ast_file = None def render_save_workspace_profile_modal(app: App) -> None: - """ - Renders a popup modal for saving the current workspace profile (projects, layout, configuration). + """Renders a popup modal for saving the current workspace profile (projects, layout, configuration). - SSDL Shape: - `[I:name_input] -> [B:scope_radio] -> [B:save_button] => [B:cancel_button]` + SSDL: `[I:name_input] -> [B:scope_radio] -> [B:save_button] => [B:cancel_button]` ASCII Layout Map: +---------------------------------------------------------+ @@ -3831,7 +3830,7 @@ def render_save_workspace_profile_modal(app: App) -> None: imgui.text("Scope:") if imgui.radio_button("Project", app._new_workspace_profile_scope == "project"): app._new_workspace_profile_scope = "project" imgui.same_line() - if imgui.radio_button("Global", app._new_workspace_profile_scope == "global"): app._new_workspace_profile_scope = "global" + if imgui.radio_button("Global", app._new_workspace_profile_scope == "global"): app._new_workspace_profile_scope = "global" imgui.separator() if imgui.button("Save", (120, 0)): @@ -3848,12 +3847,10 @@ def render_save_workspace_profile_modal(app: App) -> None: imgui.end_popup() def render_context_presets_panel(app: App) -> None: - """ - Renders the Context Presets configuration panel. Enables naming, saving, loading, + """Renders the Context Presets configuration panel. Enables naming, saving, loading, and deleting context presets. - SSDL Shape: - `[I:presets_list] -> [B:save_new_preset] => [B:presets_action_buttons]` + SSDL: `[I:presets_list] -> [B:save_new_preset] => [B:presets_action_buttons]` ASCII Layout Map: +---------------------------------------------------------+ @@ -3885,11 +3882,9 @@ def render_context_presets_panel(app: App) -> None: if imgui.button(f"Delete##{name}"): app.delete_context_preset(name) def render_context_screenshots(app: App) -> None: - """ - Renders a list of the currently attached screenshot image files. + """Renders a list of the currently attached screenshot image files. - SSDL Shape: - `[I:screenshots]` + SSDL: `[I:screenshots]` ASCII Layout Map: +---------------------------------------------------------+ @@ -3900,12 +3895,10 @@ def render_context_screenshots(app: App) -> None: for i, s in enumerate(app.screenshots): imgui.text(s) def render_context_files_table(app: App) -> None: - """ - Renders a two-column table mapping active context files to their AST view modes + """Renders a two-column table mapping active context files to their AST view modes (Definition, Signature, Hide) and slice indicators. Grouped by directories. - SSDL Shape: - `[I:group_by_dir] -> o-> [I:dir_node] -> o-> [I:file_row]` + SSDL: `[I:group_by_dir] -> o-> [I:dir_node] -> o-> [I:file_row]` ASCII Layout Map: +-------------------------------------------------------------+ @@ -3921,7 +3914,7 @@ def render_context_files_table(app: App) -> None: with imscope.table("ctx_comp_table", 2, imgui.TableFlags_.resizable | imgui.TableFlags_.borders) as active: if active: - imgui.table_setup_column("File", imgui.TableColumnFlags_.width_stretch) + imgui.table_setup_column("File", imgui.TableColumnFlags_.width_stretch) imgui.table_setup_column("Flags", imgui.TableColumnFlags_.width_fixed, 200) imgui.table_headers_row() @@ -4017,11 +4010,9 @@ def render_context_files_table(app: App) -> None: imgui.text_colored(theme.get_color("status_warning"), "[Slices Active]") def render_context_presets(app: App) -> None: - """ - Renders context preset management controls (combobox selector, update button, save-as, and delete active). + """Renders context preset management controls (combobox selector, update button, save-as, and delete active). - SSDL Shape: - `[I:presets] -> [B:presets_combo] -> [B:save_as_button] => [B:delete_active]` + SSDL: `[I:presets] -> [B:presets_combo] -> [B:save_as_button] => [B:delete_active]` ASCII Layout Map: +---------------------------------------------------------+ @@ -4055,12 +4046,12 @@ def render_context_presets(app: App) -> None: for f in app.context_files: import copy from src import models - p = f.path if hasattr(f, 'path') else str(f) - vm = f.view_mode if hasattr(f, 'view_mode') else 'summary' - slc = copy.deepcopy(f.custom_slices) if hasattr(f, 'custom_slices') else [] - msk = copy.deepcopy(f.ast_mask) if hasattr(f, 'ast_mask') else {} - sig = f.ast_signatures if hasattr(f, 'ast_signatures') else False - dfn = f.ast_definitions if hasattr(f, 'ast_definitions') else False + p = f.path if hasattr(f, 'path') else str(f) + vm = f.view_mode if hasattr(f, 'view_mode') else 'summary' + slc = copy.deepcopy(f.custom_slices) if hasattr(f, 'custom_slices') else [] + msk = copy.deepcopy(f.ast_mask) if hasattr(f, 'ast_mask') else {} + sig = f.ast_signatures if hasattr(f, 'ast_signatures') else False + dfn = f.ast_definitions if hasattr(f, 'ast_definitions') else False preset_files.append(models.ContextFileEntry(path=p, view_mode=vm, custom_slices=slc, ast_mask=msk, ast_signatures=sig, ast_definitions=dfn)) preset = models.ContextPreset(name=active, files=preset_files, screenshots=list(app.screenshots)) app.controller.save_context_preset(preset) @@ -4082,12 +4073,9 @@ def render_context_presets(app: App) -> None: root = app.controller.active_project_root for f in app.context_files: path = f.path if hasattr(f, "path") else str(f) - if not os.path.isabs(path): - full_path = os.path.join(root, path) - else: - full_path = path - if not os.path.exists(full_path): - missing.append(path) + if not os.path.isabs(path): full_path = os.path.join(root, path) + else: full_path = path + if not os.path.exists(full_path): missing.append(path) if missing: app.missing_context_files = missing @@ -4098,12 +4086,12 @@ def render_context_presets(app: App) -> None: for f in app.context_files: import copy from src import models - p = f.path if hasattr(f, 'path') else str(f) - vm = f.view_mode if hasattr(f, 'view_mode') else 'summary' - slc = copy.deepcopy(f.custom_slices) if hasattr(f, 'custom_slices') else [] - msk = copy.deepcopy(f.ast_mask) if hasattr(f, 'ast_mask') else {} - sig = f.ast_signatures if hasattr(f, 'ast_signatures') else False - dfn = f.ast_definitions if hasattr(f, 'ast_definitions') else False + p = f.path if hasattr(f, 'path') else str(f) + vm = f.view_mode if hasattr(f, 'view_mode') else 'summary' + slc = copy.deepcopy(f.custom_slices) if hasattr(f, 'custom_slices') else [] + msk = copy.deepcopy(f.ast_mask) if hasattr(f, 'ast_mask') else {} + sig = f.ast_signatures if hasattr(f, 'ast_signatures') else False + dfn = f.ast_definitions if hasattr(f, 'ast_definitions') else False preset_files.append(models.ContextFileEntry(path=p, view_mode=vm, custom_slices=slc, ast_mask=msk, ast_signatures=sig, ast_definitions=dfn)) preset = models.ContextPreset(name=name, files=preset_files, screenshots=list(app.screenshots)) app.controller.save_context_preset(preset) @@ -4118,11 +4106,9 @@ def render_context_presets(app: App) -> None: app.ui_active_context_preset = "" def render_snapshot_tab(app: App) -> None: - """ - Renders the Snapshot tab-bar, containing the resolved aggregate markdown and active system prompts. + """Renders the Snapshot tab-bar, containing the resolved aggregate markdown and active system prompts. - SSDL Shape: - `[I:aggregate_text] -> [B:copy_buttons] => [I:preview_panes]` + SSDL: `[I:aggregate_text] -> [B:copy_buttons] => [I:preview_panes]` ASCII Layout Map: +---------------------------------------------------------+ @@ -4150,13 +4136,13 @@ def render_snapshot_tab(app: App) -> None: display_md = app._focus_md_cache[cp_name] else: flat = src.project_manager.flat_config(app.controller.project, app.active_discussion) - cp = app.controller.project.get('context_presets', {}).get(cp_name) + cp = app.controller.project.get('context_presets', {}).get(cp_name) if cp: - flat["files"]["paths"] = cp.get("files", []) + flat["files"]["paths"] = cp.get("files", []) flat["screenshots"]["paths"] = cp.get("screenshots", []) - full_md, _, _ = src.aggregate.run(flat) + full_md, _, _ = src.aggregate.run(flat) app._focus_md_cache[cp_name] = full_md - display_md = full_md + display_md = full_md if imgui.button("Copy"): imgui.set_clipboard_text(display_md) with imscope.child("last_agg_md", 0, 0, True): markdown_helper.render(display_md, context_id="snapshot_agg") @@ -4167,11 +4153,9 @@ def render_snapshot_tab(app: App) -> None: markdown_helper.render(app.last_resolved_system_prompt, context_id="snapshot_sys") def render_empty_context_modal(app: App) -> None: - """ - Renders a popup modal warning the user when the context composition is empty. + """Renders a popup modal warning the user when the context composition is empty. - SSDL Shape: - `[I:warning_text] -> [B:proceed_button] => [B:cancel_button]` + SSDL: `[I:warning_text] -> [B:proceed_button] => [B:cancel_button]` ASCII Layout Map: +---------------------------------------------------------+ @@ -4192,8 +4176,8 @@ def render_empty_context_modal(app: App) -> None: imgui.text("This may result in poor AI performance or loss of project context.") imgui.separator() if imgui.button("Proceed Anyway", imgui.ImVec2(150, 0)): - if app._pending_generation_action == 'generate': app.controller._handle_generate_send() - elif app._pending_generation_action == 'md_only': app.controller._handle_md_only() + if app._pending_generation_action == 'generate': app.controller._handle_generate_send() + elif app._pending_generation_action == 'md_only': app.controller._handle_md_only() app._pending_generation_action = None imgui.close_current_popup() imgui.same_line() @@ -4202,12 +4186,10 @@ def render_empty_context_modal(app: App) -> None: imgui.end_popup() def render_context_modals(app: App) -> None: - """ - Dispatches rendering calls to sub-modals relating to context management + """Dispatches rendering calls to sub-modals relating to context management (empty context warning, file picker, missing files warning, and AST inspector). - SSDL Shape: - `[I] -> [I:modals_dispatch]` + SSDL: `[I] -> [I:modals_dispatch]` ASCII Layout Map: Conditionally opens (in order): @@ -4239,12 +4221,12 @@ def render_context_modals(app: App) -> None: for f in app.context_files: import copy from src import models - p = f.path if hasattr(f, 'path') else str(f) - vm = f.view_mode if hasattr(f, 'view_mode') else 'summary' - slc = copy.deepcopy(f.custom_slices) if hasattr(f, 'custom_slices') else [] - msk = copy.deepcopy(f.ast_mask) if hasattr(f, 'ast_mask') else {} - sig = f.ast_signatures if hasattr(f, 'ast_signatures') else False - dfn = f.ast_definitions if hasattr(f, 'ast_definitions') else False + p = f.path if hasattr(f, 'path') else str(f) + vm = f.view_mode if hasattr(f, 'view_mode') else 'summary' + slc = copy.deepcopy(f.custom_slices) if hasattr(f, 'custom_slices') else [] + msk = copy.deepcopy(f.ast_mask) if hasattr(f, 'ast_mask') else {} + sig = f.ast_signatures if hasattr(f, 'ast_signatures') else False + dfn = f.ast_definitions if hasattr(f, 'ast_definitions') else False preset_files.append(models.ContextFileEntry(path=p, view_mode=vm, custom_slices=slc, ast_mask=msk, ast_signatures=sig, ast_definitions=dfn)) preset = models.ContextPreset(name=name, files=preset_files, screenshots=list(app.screenshots)) app.controller.save_context_preset(preset) @@ -4262,10 +4244,10 @@ def render_context_modals(app: App) -> None: def _get_context_composition_state(app: App) -> tuple: files_state = [] for f in app.context_files: - p = f.path if hasattr(f, 'path') else str(f) - vm = f.view_mode if hasattr(f, 'view_mode') else 'summary' - agg = f.auto_aggregate if hasattr(f, 'auto_aggregate') else False - slc = tuple((s.get('start_line'), s.get('end_line'), s.get('tag'), s.get('comment')) for s in getattr(f, 'custom_slices', [])) + p = f.path if hasattr(f, 'path') else str(f) + vm = f.view_mode if hasattr(f, 'view_mode') else 'summary' + agg = f.auto_aggregate if hasattr(f, 'auto_aggregate') else False + slc = tuple((s.get('start_line'), s.get('end_line'), s.get('tag'), s.get('comment')) for s in getattr(f, 'custom_slices', [])) mask = tuple(sorted(getattr(f, 'ast_mask', {}).items())) files_state.append((p, vm, agg, slc, mask)) screenshots_state = tuple(app.screenshots) @@ -4287,8 +4269,8 @@ def _check_auto_refresh_context_preview(app: App) -> None: def worker(): try: app.controller.context_files = app.context_files - res = app.controller._do_generate() - app.context_preview_text = res[0] + res = app.controller._do_generate() + app.context_preview_text = res[0] except Exception: app.context_preview_text = "Error generating context preview." finally: @@ -4303,12 +4285,10 @@ def _check_auto_refresh_context_preview(app: App) -> None: app.controller.submit_io(worker) def render_context_preview_window(app: App) -> None: - """ - Renders the Context Preview window. Automatically refreshes aggregated context previews in the background + """Renders the Context Preview window. Automatically refreshes aggregated context previews in the background and renders formatted markdown text. - SSDL Shape: - `[I:preview_text] -> [B:clipboard_button] => [I:preview_box]` + SSDL: `[I:preview_text] -> [B:clipboard_button] => [I:preview_box]` ASCII Layout Map: +---------------------------------------------------------+ @@ -4330,7 +4310,7 @@ def render_context_preview_window(app: App) -> None: if exp: if imgui.button("Close"): app.show_windows["Context Preview"] = False - app.ui_separate_context_preview = False + app.ui_separate_context_preview = False imgui.same_line() if imgui.button("Copy to Clipboard"): imgui.set_clipboard_text(app.context_preview_text) @@ -4342,12 +4322,10 @@ def render_context_preview_window(app: App) -> None: #region: Discussions def render_discussion_hub(app: App) -> None: - """ - Top-level hub for the Discussion panel. Houses tabs for Discussion, Context Composition, + """Top-level hub for the Discussion panel. Houses tabs for Discussion, Context Composition, Context Preview (inline or detached), Snapshot, and Takes. - SSDL Shape: - `[B:pop_out_toggle] -> [I:tab_bar] => [I:active_tab_content]` + SSDL: `[B:pop_out_toggle] -> [I:tab_bar] => [I:active_tab_content]` ASCII Layout Map: +---------------------------------------------------------+ @@ -4383,12 +4361,10 @@ def render_discussion_hub(app: App) -> None: return def render_thinking_trace(app: App, entry: dict, segments: list[dict], entry_index: int, is_standalone: bool = False) -> None: - """ - Renders a collapsible thinking-trace section within a discussion entry bubble. + """Renders a collapsible thinking-trace section within a discussion entry bubble. Displays each reasoning segment labeled by its marker tag (e.g. [thinking]). - SSDL Shape: - `[I:segment_list] -> [B:read_pure_toggle] => [I:trace_child]` + SSDL: `[I:segment_list] -> [B:read_pure_toggle] => [I:trace_child]` ASCII Layout Map: +----------------------------------------------------------+ @@ -4426,22 +4402,18 @@ def render_thinking_trace(app: App, entry: dict, segments: list[dict], entry_ind imgui.text_colored(C_TC(), f"[{marker}]") if thinking_read_mode: if app.ui_word_wrap: - with imscope.text_wrap(imgui.get_content_region_avail().x): - imgui.text(content) - else: - imgui.text(content) + with imscope.text_wrap(imgui.get_content_region_avail().x): imgui.text(content) + else: imgui.text(content) else: render_selectable_label(app, f"think_text_{entry_index}_{idx}", content, multiline=True, height=-1) imgui.separator() def render_discussion_entry(app: App, entry: dict, index: int) -> None: - """ - Renders a single discussion message entry as a colored visual bubble. + """Renders a single discussion message entry as a colored visual bubble. Supports collapsible states, read/edit mode toggles, role selection, input/output token metrics, and action footers. - SSDL Shape: - `[I:header] -> [B:collapsed] => [I:preview] | [I:body] -> [I:footer]` + SSDL: `[I:header] -> [B:collapsed] => [I:preview] | [I:body] -> [I:footer]` ASCII Layout Map: +-------------------------------------------------------------+ @@ -7139,13 +7111,13 @@ def render_task_dag_panel(app: App) -> None: # 4. Task DAG Visualizer imgui.end_combo() if imgui.button("Create"): new_ticket = { - "id": app.ui_new_ticket_id, + "id": app.ui_new_ticket_id, "description": app.ui_new_ticket_desc, - "status": "todo", - "priority": app.ui_new_ticket_priority, + "status": "todo", + "priority": app.ui_new_ticket_priority, "assigned_to": "tier3-worker", "target_file": app.ui_new_ticket_target, - "depends_on": [d.strip() for d in app.ui_new_ticket_deps.split(",") if d.strip()] + "depends_on": [d.strip() for d in app.ui_new_ticket_deps.split(",") if d.strip()] } app.active_tickets.append(new_ticket) app._show_add_ticket_form = False