progress on context composition
This commit is contained in:
+21
-1
@@ -2933,9 +2933,25 @@ class AppController:
|
||||
self.ui_file_paths = [f.path for f in preset.files]
|
||||
self.screenshots = list(preset.screenshots)
|
||||
self._save_active_project()
|
||||
# We need to tell gui_2 to populate the full FileItem state from the preset,
|
||||
# which it does in _handle_refresh_from_project. But we also need to pass the detailed properties.
|
||||
# We will let the project_manager handle merging in the preset files via configuration next turn.
|
||||
# Wait, project manager doesn't load preset files into self.files automatically here.
|
||||
# Let's write the preset files into self.project["files"] directly.
|
||||
import copy
|
||||
self.project.setdefault("files", {})["paths"] = [
|
||||
{
|
||||
"path": f.path,
|
||||
"view_mode": f.view_mode,
|
||||
"custom_slices": copy.deepcopy(f.custom_slices),
|
||||
"ast_mask": copy.deepcopy(f.ast_mask),
|
||||
"ast_signatures": getattr(f, "ast_signatures", False),
|
||||
"ast_definitions": getattr(f, "ast_definitions", False)
|
||||
} for f in preset.files
|
||||
]
|
||||
self._save_active_project()
|
||||
return preset
|
||||
|
||||
|
||||
def _cb_load_track(self, track_id: str) -> None:
|
||||
"""
|
||||
[C: src/gui_2.py:App._render_mma_track_browser]
|
||||
@@ -3445,6 +3461,10 @@ class AppController:
|
||||
flat = project_manager.flat_config(self.project, self.active_discussion, track_id=track_id)
|
||||
flat.setdefault("files", {})["paths"] = self.context_files
|
||||
|
||||
# Configure MCP so that aggregate.py can fetch skeletons for external files (e.g. gencpp)
|
||||
file_dicts = [f.to_dict() if hasattr(f, 'to_dict') else {"path": str(f)} for f in self.context_files]
|
||||
mcp_client.configure(file_dicts, [self.active_project_root] if self.active_project_root else None)
|
||||
|
||||
persona = self.personas.get(self.ui_active_persona)
|
||||
strategy = persona.aggregation_strategy if persona else "auto"
|
||||
|
||||
|
||||
+44
-10
@@ -153,12 +153,15 @@ class App:
|
||||
for f in self.context_files:
|
||||
p = f.path if hasattr(f, 'path') else str(f)
|
||||
vm = f.view_mode if hasattr(f, 'view_mode') else 'summary'
|
||||
preset_files.append(models.ContextFileEntry(path=p, view_mode=vm))
|
||||
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(self.screenshots))
|
||||
self.controller.save_context_preset(preset)
|
||||
self.ui_new_context_preset_name = ""
|
||||
self.show_missing_files_modal = False
|
||||
|
||||
self.show_missing_files_modal = False
|
||||
self.controller._predefined_callbacks['get_app_debug_info'] = lambda: self.app_debug_info
|
||||
self.controller._gettable_fields['app_debug_info'] = 'app_debug_info'
|
||||
self.controller._predefined_callbacks['save_context_preset_force'] = _save_context_preset_force
|
||||
@@ -3011,6 +3014,9 @@ def render_ast_inspector_modal(app: App) -> None:
|
||||
imgui.same_line()
|
||||
imgui.text(f"[{kind}] {name}")
|
||||
|
||||
if imgui.is_item_hovered():
|
||||
app._hovered_ast_node = full_path
|
||||
|
||||
# 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
|
||||
@@ -3061,6 +3067,9 @@ def render_ast_inspector_modal(app: App) -> None:
|
||||
elif mode == 'sig':
|
||||
# Blue, 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(0, 0, 255, 0.2)))
|
||||
elif deepest_node and deepest_node['full_path'] == getattr(app, '_hovered_ast_node', None):
|
||||
# Yellow, alpha 0.3 for hover
|
||||
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, 255, 0, 0.3)))
|
||||
|
||||
imgui.text(f"{line_num:4} | {line_text}")
|
||||
imgui.end_child()
|
||||
@@ -4126,7 +4135,7 @@ def render_text_viewer_window(app: App) -> None:
|
||||
"""Renders the standalone text/code/markdown viewer window."""
|
||||
if not app.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 - {app.text_viewer_title}", app.show_text_viewer)
|
||||
expanded, opened = imgui.begin(f"{app.text_viewer_title or 'Text Viewer'}###Text_Viewer", app.show_text_viewer)
|
||||
app.show_text_viewer = bool(opened)
|
||||
if not opened:
|
||||
app.ui_editing_slices_file = None
|
||||
@@ -4148,20 +4157,45 @@ def render_text_viewer_window(app: App) -> None:
|
||||
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)
|
||||
|
||||
imgui.same_line()
|
||||
if imgui.button("Edit Tags"): imgui.open_popup("Edit Context Tags")
|
||||
|
||||
if imgui.begin_popup("Edit Context Tags"):
|
||||
tags = app.controller.project.setdefault("context_tags", ["auto-ast", "bug", "feature", "important"])
|
||||
imgui.text("Context Tags")
|
||||
imgui.separator()
|
||||
to_remove_tag = -1
|
||||
for i, t in enumerate(tags):
|
||||
imgui.push_id(f"tag_{i}")
|
||||
imgui.set_next_item_width(150)
|
||||
ch, new_t = imgui.input_text("##t", t)
|
||||
if ch: tags[i] = new_t
|
||||
imgui.same_line()
|
||||
if imgui.button("X"): to_remove_tag = i
|
||||
imgui.pop_id()
|
||||
if to_remove_tag != -1: tags.pop(to_remove_tag)
|
||||
if imgui.button("+ Add Tag"): tags.append("new-tag")
|
||||
if imgui.button("Close"): imgui.close_current_popup()
|
||||
imgui.end_popup()
|
||||
|
||||
to_remove = -1
|
||||
tags = app.controller.project.get("context_tags", ["auto-ast", "bug", "feature", "important"])
|
||||
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()
|
||||
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', ''))
|
||||
current_tag = slc.get('tag', '')
|
||||
if current_tag not in tags and current_tag: tags.append(current_tag)
|
||||
tag_idx = tags.index(current_tag) if current_tag in tags else 0
|
||||
imgui.set_next_item_width(150)
|
||||
ch_tag, new_tag_idx = imgui.combo("Category/Tag", tag_idx, tags)
|
||||
if ch_tag: slc['tag'] = tags[new_tag_idx]
|
||||
imgui.same_line(); imgui.set_next_item_width(300); changed_comm, new_comm = imgui.input_text("Note/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: app.ui_editing_slices_file.custom_slices.pop(to_remove)
|
||||
imgui.separator()
|
||||
if imgui.button("Copy"): imgui.set_clipboard_text(app.text_viewer_content)
|
||||
imgui.separator()
|
||||
if imgui.button("Copy"): imgui.set_clipboard_text(app.text_viewer_content)
|
||||
imgui.same_line(); _, app.text_viewer_wrap = imgui.checkbox("Word Wrap", app.text_viewer_wrap)
|
||||
imgui.separator()
|
||||
renderer = markdown_helper.get_renderer(); tv_type = getattr(app, "text_viewer_type", "text")
|
||||
|
||||
+7
-1
@@ -827,12 +827,15 @@ class ContextFileEntry:
|
||||
path: str
|
||||
view_mode: str = "summary"
|
||||
custom_slices: list = field(default_factory=list)
|
||||
ast_mask: dict = field(default_factory=dict)
|
||||
ast_signatures: bool = False
|
||||
ast_definitions: bool = False
|
||||
|
||||
def to_dict(self) -> dict[str, Any]:
|
||||
"""
|
||||
[C: src/personas.py:PersonaManager.save_persona, src/presets.py:PresetManager.save_preset, src/project_manager.py:save_project, src/project_manager.py:save_track_state, src/tool_presets.py:ToolPresetManager.save_bias_profile, src/tool_presets.py:ToolPresetManager.save_preset, src/workspace_manager.py:WorkspaceManager.save_profile, tests/test_bias_models.py:test_bias_profile_model, tests/test_bias_models.py:test_tool_model, tests/test_bias_models.py:test_tool_preset_extension, tests/test_context_presets_models.py:test_context_preset_serialization, tests/test_context_presets_models.py:test_file_view_preset_serialization, tests/test_custom_slices_annotations.py:test_file_item_custom_slices_round_trip_annotations, tests/test_custom_slices_annotations.py:test_file_item_custom_slices_serialization_with_annotations, tests/test_event_serialization.py:test_user_request_event_serialization, tests/test_external_editor.py:TestExternalEditorConfig.test_to_dict, tests/test_external_editor.py:TestTextEditorConfig.test_to_dict, tests/test_file_item_model.py:test_file_item_to_dict, tests/test_gui_events_v2.py:test_user_request_event_payload, tests/test_history_manager.py:TestHistoryManager.test_snapshot_roundtrip, tests/test_mcp_config.py:test_mcp_configuration_to_from_dict, tests/test_mcp_config.py:test_mcp_server_config_to_from_dict, tests/test_per_ticket_model.py:test_model_override_serialization, tests/test_persona_id.py:test_ticket_persona_id_serialization, tests/test_persona_models.py:test_persona_defaults, tests/test_persona_models.py:test_persona_serialization, tests/test_slice_editor_behavior.py:test_add_slice_with_annotations, tests/test_thinking_gui.py:test_thinking_segment_model_compatibility, tests/test_ticket_queue.py:test_ticket_to_dict_priority, tests/test_tiered_aggregation.py:test_persona_aggregation_strategy, tests/test_track_state_schema.py:test_track_state_to_dict, tests/test_track_state_schema.py:test_track_state_to_dict_with_none, tests/test_ui_summary_only_removal.py:test_file_item_serialization_with_flags]
|
||||
"""
|
||||
return {"path": self.path, "view_mode": self.view_mode, "custom_slices": self.custom_slices}
|
||||
return {"path": self.path, "view_mode": self.view_mode, "custom_slices": self.custom_slices, "ast_mask": self.ast_mask, "ast_signatures": self.ast_signatures, "ast_definitions": self.ast_definitions}
|
||||
|
||||
@classmethod
|
||||
def from_dict(cls, data: dict[str, Any]) -> "ContextFileEntry":
|
||||
@@ -843,6 +846,9 @@ class ContextFileEntry:
|
||||
path=data.get("path", ""),
|
||||
view_mode=data.get("view_mode", "summary"),
|
||||
custom_slices=data.get("custom_slices", []),
|
||||
ast_mask=data.get("ast_mask", {}),
|
||||
ast_signatures=data.get("ast_signatures", False),
|
||||
ast_definitions=data.get("ast_definitions", False),
|
||||
)
|
||||
|
||||
@dataclass
|
||||
|
||||
Reference in New Issue
Block a user