Progress on context composition
This commit is contained in:
@@ -205,12 +205,20 @@ def build_file_items(base_dir: Path, files: list[str | dict[str, Any]]) -> list[
|
||||
if path.suffix == ".py":
|
||||
if not parser: parser = ASTParser("python")
|
||||
content = parser.get_skeleton(content, path=str(path))
|
||||
elif path.suffix in ['.c', '.h', '.cpp', '.hpp', '.cxx', '.cc']:
|
||||
from src import mcp_client
|
||||
if path.suffix in ['.c', '.h']: content = mcp_client.ts_c_get_skeleton(str(path))
|
||||
else: content = mcp_client.ts_cpp_get_skeleton(str(path))
|
||||
else:
|
||||
content = summarize.summarise_file(path, content)
|
||||
elif view_mode == "outline":
|
||||
if path.suffix == ".py":
|
||||
if not parser: parser = ASTParser("python")
|
||||
content = parser.get_code_outline(content, path=str(path))
|
||||
elif path.suffix in ['.c', '.h', '.cpp', '.hpp', '.cxx', '.cc']:
|
||||
from src import mcp_client
|
||||
if path.suffix in ['.c', '.h']: content = mcp_client.ts_c_get_code_outline(str(path))
|
||||
else: content = mcp_client.ts_cpp_get_code_outline(str(path))
|
||||
else:
|
||||
content = summarize.summarise_file(path, content)
|
||||
elif view_mode == "none":
|
||||
|
||||
@@ -955,6 +955,7 @@ class AppController:
|
||||
self.ui_new_track_name: str = ""
|
||||
self.ui_new_track_desc: str = ""
|
||||
self.ui_new_track_type: str = "feature"
|
||||
self.ui_project_conductor_dir: str = ""
|
||||
self.ui_conductor_setup_summary: str = ""
|
||||
self.ui_last_script_text: str = ""
|
||||
self.ui_last_script_output: str = ""
|
||||
|
||||
+62
-12
@@ -18,6 +18,13 @@ import time
|
||||
import tomli_w
|
||||
import typing
|
||||
from contextlib import ExitStack, nullcontext
|
||||
|
||||
# Ensure thirdparty is in sys.path for defer
|
||||
_project_root = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
|
||||
_thirdparty = os.path.join(_project_root, "thirdparty")
|
||||
if _thirdparty not in sys.path:
|
||||
sys.path.insert(0, _thirdparty)
|
||||
|
||||
from defer import defer
|
||||
from imgui_bundle import imgui, hello_imgui, immapp, imgui_node_editor as ed, imgui_color_text_edit as ced
|
||||
from pathlib import Path
|
||||
@@ -923,8 +930,21 @@ class App:
|
||||
"""
|
||||
from src import mcp_client
|
||||
import re
|
||||
mcp_client.configure([{"path": f_item.path}])
|
||||
outline = mcp_client.py_get_code_outline(f_item.path)
|
||||
from pathlib import Path
|
||||
import os
|
||||
proj_dir = str(Path(self.controller.active_project_path).parent.resolve()) if getattr(self, 'controller', None) and self.controller.active_project_path else None
|
||||
abs_path = f_item.path if os.path.isabs(f_item.path) else os.path.join(proj_dir or '.', f_item.path)
|
||||
mcp_client.configure([{"path": abs_path}], [proj_dir] if proj_dir else None)
|
||||
|
||||
f_path_lower = f_item.path.lower()
|
||||
try:
|
||||
if f_path_lower.endswith('.py'): outline = mcp_client.py_get_code_outline(abs_path)
|
||||
elif f_path_lower.endswith(('.c', '.h')): outline = mcp_client.ts_c_get_code_outline(abs_path)
|
||||
elif f_path_lower.endswith(('.cpp', '.hpp', '.cxx', '.cc')): outline = mcp_client.ts_cpp_get_code_outline(abs_path)
|
||||
else: return
|
||||
except Exception:
|
||||
return
|
||||
|
||||
if outline.startswith("ERROR") or outline.startswith("ACCESS DENIED"):
|
||||
return
|
||||
pattern = re.compile(r'^\s*\[(.*?)\] (.*?) \(Lines (\d+)-(\d+)\)', re.MULTILINE)
|
||||
@@ -2841,8 +2861,13 @@ def render_context_batch_actions(app: App, total_lines: int, total_ast: int) ->
|
||||
if not app.context_files:
|
||||
app.context_preview_text = "# Context Composition Empty\n\nNo files have been added to the context composition yet."
|
||||
else:
|
||||
app.controller.context_files = app.context_files
|
||||
app.context_preview_text = app.controller._do_generate()[0]
|
||||
try:
|
||||
app.controller.context_files = app.context_files
|
||||
app.context_preview_text = app.controller._do_generate()[0]
|
||||
except Exception as e:
|
||||
import traceback
|
||||
err = traceback.format_exc()
|
||||
app.context_preview_text = f"# Error generating preview\n\n```python\n{err}\n```"
|
||||
app.show_windows["Context Preview"] = True
|
||||
imgui.same_line()
|
||||
imgui.text(f" | Total: {len(app.context_files)} files, {total_lines} lines, {total_ast} AST elements")
|
||||
@@ -2911,7 +2936,8 @@ def render_ast_inspector_modal(app: App) -> None:
|
||||
app._show_ast_inspector = False
|
||||
|
||||
#region: AST Inspector
|
||||
expanded, opened = imgui.begin_popup_modal('AST Inspector', True, imgui.WindowFlags_.always_auto_resize)
|
||||
imgui.set_next_window_size(imgui.ImVec2(1200, 800), imgui.Cond_.first_use_ever)
|
||||
expanded, opened = imgui.begin_popup_modal('AST Inspector', True, imgui.WindowFlags_.none)
|
||||
if opened:
|
||||
if expanded:
|
||||
if app.ui_inspecting_ast_file is None:
|
||||
@@ -2923,6 +2949,11 @@ def render_ast_inspector_modal(app: App) -> None:
|
||||
if f_path != app._cached_ast_file_path:
|
||||
outline = ""
|
||||
try:
|
||||
from src import mcp_client
|
||||
from pathlib import Path
|
||||
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)
|
||||
else: outline = mcp_client.ts_cpp_get_code_outline(f_path)
|
||||
@@ -2959,12 +2990,14 @@ def render_ast_inspector_modal(app: App) -> None:
|
||||
imgui.text(f"Inspecting AST: {f_path}")
|
||||
imgui.separator()
|
||||
|
||||
avail = imgui.get_content_region_avail()
|
||||
table_height = max(100.0, avail.y - imgui.get_frame_height_with_spacing() - 10)
|
||||
#region: ast_dual_pane
|
||||
if imgui.begin_table('ast_dual_pane', 2, imgui.TableFlags_.resizable | imgui.TableFlags_.borders_inner_v):
|
||||
if imgui.begin_table('ast_dual_pane', 2, imgui.TableFlags_.resizable | imgui.TableFlags_.borders_inner_v, imgui.ImVec2(0, table_height)):
|
||||
imgui.table_next_column()
|
||||
|
||||
#region: LEFT COLUMN (Tree) ---
|
||||
imgui.begin_child("ast_tree_scroll", imgui.ImVec2(0, 600), True)
|
||||
imgui.begin_child("ast_tree_scroll", imgui.ImVec2(0, 0), True)
|
||||
if True:
|
||||
if not app._cached_ast_nodes: imgui.text("No AST nodes found or error fetching outline.")
|
||||
else:
|
||||
@@ -2977,7 +3010,14 @@ def render_ast_inspector_modal(app: App) -> None:
|
||||
imgui.dummy(imgui.ImVec2(indent * 10, 0))
|
||||
imgui.same_line()
|
||||
imgui.text(f"[{kind}] {name}")
|
||||
imgui.same_line(imgui.get_window_width() - 200)
|
||||
|
||||
# Calculate space left and align radio buttons to the right
|
||||
btn_width = 150 # Estimated width of the 3 radio buttons
|
||||
avail_width = imgui.get_content_region_avail().x
|
||||
if avail_width > btn_width:
|
||||
imgui.same_line(imgui.get_window_width() - btn_width)
|
||||
else:
|
||||
imgui.same_line()
|
||||
|
||||
current_mode = f_item.ast_mask.get(full_path, 'hide')
|
||||
|
||||
@@ -2994,7 +3034,7 @@ def render_ast_inspector_modal(app: App) -> None:
|
||||
imgui.table_next_column()
|
||||
|
||||
#region: RIGHT COLUMN (Content) ---
|
||||
imgui.begin_child("ast_content_scroll", imgui.ImVec2(0, 600), True)
|
||||
imgui.begin_child("ast_content_scroll", imgui.ImVec2(0, 0), True)
|
||||
if True:
|
||||
if not hasattr(app, '_cached_ast_file_lines') or not app._cached_ast_file_lines:
|
||||
imgui.text("No file content loaded.")
|
||||
@@ -3117,8 +3157,10 @@ def render_context_files_table(app: App) -> None:
|
||||
|
||||
f_path = f_item.path if hasattr(f_item, "path") else str(f_item)
|
||||
is_sel = f_path in app.ui_selected_context_files
|
||||
f_item.auto_aggregate = is_sel
|
||||
changed_sel, is_sel = imgui.checkbox(f"##sel{i}", is_sel)
|
||||
if changed_sel:
|
||||
f_item.auto_aggregate = is_sel
|
||||
if imgui.get_io().key_shift and app._last_selected_context_index != -1:
|
||||
start = min(app._last_selected_context_index, i)
|
||||
end = max(app._last_selected_context_index, i)
|
||||
@@ -4104,6 +4146,9 @@ def render_text_viewer_window(app: App) -> None:
|
||||
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
|
||||
imgui.same_line()
|
||||
if imgui.button("Auto-Populate AST Slices"): app._populate_auto_slices(app.ui_editing_slices_file)
|
||||
|
||||
to_remove = -1
|
||||
for idx, slc in enumerate(app.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()
|
||||
@@ -4127,14 +4172,19 @@ def render_text_viewer_window(app: App) -> None:
|
||||
lines = app.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()
|
||||
is_sliced = any(slc['start_line'] <= line_num <= slc['end_line'] for slc in app.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)))
|
||||
|
||||
is_auto_sliced = any(slc['start_line'] <= line_num <= slc['end_line'] for slc in app.ui_editing_slices_file.custom_slices if slc.get('tag') == 'auto-ast')
|
||||
is_manual_sliced = any(slc['start_line'] <= line_num <= slc['end_line'] for slc in app.ui_editing_slices_file.custom_slices if slc.get('tag') != 'auto-ast')
|
||||
|
||||
if is_manual_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)))
|
||||
elif is_auto_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(0, 255, 0, 0.15)))
|
||||
|
||||
if app._slice_sel_start != -1 and app._slice_sel_end != -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 + 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(): app._slice_sel_start = line_num; app._slice_sel_end = line_num
|
||||
if imgui.is_item_hovered() and imgui.is_mouse_down(0): 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
|
||||
elif tv_type in renderer._lang_map:
|
||||
if app._text_viewer_editor is None:
|
||||
app._text_viewer_editor = ced.TextEditor(); app._text_viewer_editor.set_read_only_enabled(True); app._text_viewer_editor.set_show_line_numbers_enabled(True)
|
||||
|
||||
Reference in New Issue
Block a user