feat(gui): Implement Context Hub UI for context presets

This commit is contained in:
2026-03-18 00:13:50 -04:00
parent 1e223b46b0
commit 573f5ee5d1
2 changed files with 114 additions and 2 deletions

View File

@@ -108,6 +108,16 @@ class App:
self.show_windows.setdefault("Diagnostics", False)
self.controller.start_services(self)
self.controller._predefined_callbacks['_render_text_viewer'] = self._render_text_viewer
self.controller._predefined_callbacks['save_context_preset'] = self.save_context_preset
self.controller._predefined_callbacks['load_context_preset'] = self.load_context_preset
self.controller._predefined_callbacks['set_ui_file_paths'] = lambda p: setattr(self, 'ui_file_paths', p)
self.controller._predefined_callbacks['set_ui_screenshot_paths'] = lambda p: setattr(self, 'ui_screenshot_paths', p)
def simulate_save_preset(name: str):
from src import models
self.files = [models.FileItem(path='test.py')]
self.screenshots = ['test.png']
self.save_context_preset(name)
self.controller._predefined_callbacks['simulate_save_preset'] = simulate_save_preset
self.show_preset_manager_window = False
self.show_tool_preset_manager_window = False
self.show_persona_editor_window = False
@@ -221,8 +231,8 @@ class App:
self.ui_tool_filter_category = "All"
self.ui_discussion_split_h = 300.0
self.shader_uniforms = {'crt': 1.0, 'scanline': 0.5, 'bloom': 0.8}
def _handle_approve_tool(self, user_data=None) -> None:
self.shader_uniforms = {'crt': 1.0, 'scanline': 0.5, 'bloom': 0.8}
self.ui_new_context_preset_name = ""
"""UI-level wrapper for approving a pending tool execution ask."""
self._handle_approve_ask()
@@ -280,6 +290,46 @@ class App:
pass
self.controller.shutdown()
def save_context_preset(self, name: str) -> None:
sys.stderr.write(f"[DEBUG] save_context_preset called with: {name}\n")
sys.stderr.flush()
if 'context_presets' not in self.controller.project:
self.controller.project['context_presets'] = {}
self.controller.project['context_presets'][name] = {
'files': [f.to_dict() if hasattr(f, 'to_dict') else {'path': str(f)} for f in self.files],
'screenshots': list(self.screenshots)
}
self.controller._save_active_project()
sys.stderr.write(f"[DEBUG] save_context_preset finished. Project keys: {list(self.controller.project.keys())}\n")
sys.stderr.flush()
def load_context_preset(self, name: str) -> None:
presets = self.controller.project.get('context_presets', {})
if name in presets:
preset = presets[name]
self.files = [models.FileItem.from_dict(f) if isinstance(f, dict) else models.FileItem(path=str(f)) for f in preset.get('files', [])]
self.screenshots = list(preset.get('screenshots', []))
def delete_context_preset(self, name: str) -> None:
if 'context_presets' in self.controller.project:
self.controller.project['context_presets'].pop(name, None)
self.controller._save_active_project()
@property
def ui_file_paths(self) -> list[str]:
return [f.path if hasattr(f, 'path') else str(f) for f in self.files]
@ui_file_paths.setter
def ui_file_paths(self, paths: list[str]) -> None:
self.files = [models.FileItem(path=p) for p in paths]
@property
def ui_screenshot_paths(self) -> list[str]:
return self.screenshots
@ui_screenshot_paths.setter
def ui_screenshot_paths(self, paths: list[str]) -> None:
self.screenshots = paths
def _test_callback_func_write_to_file(self, data: str) -> None:
"""A dummy function that a custom_callback would execute for testing."""
# Ensure the directory exists if running from a different cwd
@@ -587,6 +637,9 @@ class App:
if imgui.begin_tab_item('Paths')[0]:
self._render_paths_panel()
imgui.end_tab_item()
if imgui.begin_tab_item('Context Presets')[0]:
self._render_context_presets_panel()
imgui.end_tab_item()
imgui.end_tab_bar()
imgui.end()
if self.show_windows.get("Files & Media", False):
@@ -1698,6 +1751,30 @@ class App:
self.ai_status = "paths reset to defaults"
if self.perf_profiling_enabled: self.perf_monitor.end_component("_render_paths_panel")
def _render_context_presets_panel(self) -> None:
imgui.text_colored(C_IN, "Context Presets")
imgui.separator()
changed, new_name = imgui.input_text("Preset Name##new_ctx", self.ui_new_context_preset_name)
if changed: self.ui_new_context_preset_name = new_name
imgui.same_line()
if imgui.button("Save Current"):
if self.ui_new_context_preset_name.strip():
self.save_context_preset(self.ui_new_context_preset_name.strip())
imgui.separator()
presets = self.controller.project.get('context_presets', {})
for name in sorted(presets.keys()):
preset = presets[name]
n_files = len(preset.get('files', []))
n_shots = len(preset.get('screenshots', []))
imgui.text(f"{name} ({n_files} files, {n_shots} shots)")
imgui.same_line()
if imgui.button(f"Load##{name}"):
self.load_context_preset(name)
imgui.same_line()
if imgui.button(f"Delete##{name}"):
self.delete_context_preset(name)
def _render_track_proposal_modal(self) -> None:
if self._show_track_proposal_modal:
imgui.open_popup("Track Proposal")