began to go through the files and organize imports and gui_2.py's new context defs
still a bunch to sift through after the last ai passes
This commit is contained in:
+133
-134
@@ -17,7 +17,6 @@ import threading
|
||||
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__)))
|
||||
@@ -25,16 +24,16 @@ _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
|
||||
from tkinter import filedialog, Tk
|
||||
from typing import Optional, Any
|
||||
from defer import defer
|
||||
from contextlib import ExitStack, nullcontext
|
||||
# from defer import defer
|
||||
from pathlib import Path
|
||||
from tkinter import filedialog, Tk
|
||||
from typing import Optional, Any
|
||||
from imgui_bundle import imgui, hello_imgui, immapp, imgui_node_editor as ed, imgui_color_text_edit as ced
|
||||
from pathlib import Path
|
||||
from tkinter import filedialog, Tk
|
||||
from typing import Optional, Any
|
||||
|
||||
from src.diff_viewer import apply_patch_to_file
|
||||
from src import ai_client
|
||||
from src import aggregate
|
||||
@@ -61,6 +60,7 @@ from src import theme_nerv_fx as theme_fx
|
||||
from src import thinking_parser
|
||||
from src import workspace_manager
|
||||
from src.hot_reloader import HotReloader
|
||||
|
||||
if sys.platform == "win32":
|
||||
import win32gui
|
||||
import win32con
|
||||
@@ -2784,8 +2784,6 @@ def render_files_and_media(app: App) -> None:
|
||||
if p not in app.screenshots: app.screenshots.append(p)
|
||||
return
|
||||
|
||||
#endregion: Context Management
|
||||
|
||||
def render_context_batch_actions(app: App, total_lines: int, total_ast: int) -> None:
|
||||
imgui.text("Batch:")
|
||||
for mode in ["full", "summary", "skeleton", "outline", "masked", "none"]:
|
||||
@@ -3361,6 +3359,130 @@ def render_snapshot_tab(app: App) -> None:
|
||||
with imscope.child("last_sys_prompt", 0, 0, True):
|
||||
markdown_helper.render(app.last_resolved_system_prompt, context_id="snapshot_sys")
|
||||
|
||||
def render_empty_context_modal(app: App) -> None:
|
||||
if app.show_empty_context_modal:
|
||||
imgui.open_popup("Empty Context Warning")
|
||||
app.show_empty_context_modal = False
|
||||
|
||||
if imgui.begin_popup_modal("Empty Context Warning", True, imgui.WindowFlags_.always_auto_resize)[0]:
|
||||
imgui.text_colored(theme.get_color("status_warning"), "WARNING: Empty Context Composition")
|
||||
imgui.text("You are attempting to generate a response without any files selected.")
|
||||
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()
|
||||
app._pending_generation_action = None
|
||||
imgui.close_current_popup()
|
||||
imgui.same_line()
|
||||
if imgui.button("Cancel", imgui.ImVec2(120, 0)):
|
||||
imgui.close_current_popup()
|
||||
imgui.end_popup()
|
||||
|
||||
def render_context_modals(app: App) -> None:
|
||||
render_empty_context_modal(app)
|
||||
render_add_context_files_modal(app)
|
||||
|
||||
if app.show_missing_files_modal:
|
||||
imgui.open_popup("Missing Files Warning")
|
||||
app.show_missing_files_modal = False
|
||||
|
||||
if imgui.begin_popup_modal("Missing Files Warning", True, imgui.WindowFlags_.always_auto_resize)[0]:
|
||||
imgui.text("The following files are missing from disk:")
|
||||
imgui.separator()
|
||||
imgui.begin_child("missing_files_list", imgui.ImVec2(0, 150), True)
|
||||
for f in app.missing_context_files:
|
||||
imgui.text_colored(theme.get_color("status_error"), f)
|
||||
imgui.end_child()
|
||||
imgui.separator()
|
||||
|
||||
if imgui.button("Save Anyway") or getattr(app, "_pending_save_anyway_click", False):
|
||||
app._pending_save_anyway_click = False
|
||||
name = app.target_context_preset_name
|
||||
preset_files = []
|
||||
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
|
||||
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)
|
||||
app.ui_new_context_preset_name = ""
|
||||
imgui.close_current_popup()
|
||||
|
||||
imgui.same_line()
|
||||
if imgui.button("Cancel"):
|
||||
imgui.close_current_popup()
|
||||
|
||||
imgui.end_popup()
|
||||
|
||||
render_ast_inspector_modal(app)
|
||||
|
||||
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', []))
|
||||
mask = tuple(sorted(getattr(f, 'ast_mask', {}).items()))
|
||||
files_state.append((p, vm, agg, slc, mask))
|
||||
screenshots_state = tuple(app.screenshots)
|
||||
return (tuple(files_state), screenshots_state)
|
||||
|
||||
def _check_auto_refresh_context_preview(app: App) -> None:
|
||||
current_state = _get_context_composition_state(app)
|
||||
if not hasattr(app, "_last_context_preview_state") or app._last_context_preview_state != current_state:
|
||||
app._last_context_preview_state = current_state
|
||||
if not any(getattr(f, 'auto_aggregate', False) for f in app.context_files) and not app.screenshots:
|
||||
app.context_preview_text = "# Context Composition Empty\n\nNo files or screenshots have been selected for aggregation."
|
||||
return
|
||||
|
||||
if getattr(app, "_is_generating_preview", False):
|
||||
app._pending_preview_refresh = True
|
||||
return
|
||||
|
||||
app._is_generating_preview = True
|
||||
def worker():
|
||||
try:
|
||||
app.controller.context_files = app.context_files
|
||||
res = app.controller._do_generate()
|
||||
app.context_preview_text = res[0]
|
||||
except Exception:
|
||||
app.context_preview_text = "Error generating context preview."
|
||||
finally:
|
||||
app._is_generating_preview = False
|
||||
if getattr(app, "_pending_preview_refresh", False):
|
||||
app._pending_preview_refresh = False
|
||||
# This will trigger again on next GUI frame because _last_context_preview_state
|
||||
# will be slightly behind if another change happened during the thread.
|
||||
# Or we just clear the state so it re-triggers.
|
||||
app._last_context_preview_state = None
|
||||
|
||||
import threading
|
||||
threading.Thread(target=worker, daemon=True).start()
|
||||
|
||||
def render_context_preview_window(app: App) -> None:
|
||||
_check_auto_refresh_context_preview(app)
|
||||
with imscope.window("Context Preview", app.show_windows["Context Preview"]) as (exp, opened):
|
||||
app.show_windows["Context Preview"] = bool(opened)
|
||||
if not opened:
|
||||
app.ui_separate_context_preview = False
|
||||
if exp:
|
||||
if imgui.button("Close"):
|
||||
app.show_windows["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)
|
||||
with imscope.child("ctx_preview_scroll", 0, 0, True):
|
||||
markdown_helper.render(app.context_preview_text, context_id="ctx_preview")
|
||||
|
||||
#endregion: Context Management
|
||||
|
||||
#region: Discussions
|
||||
@@ -3587,6 +3709,7 @@ def render_session_insights_panel(app: App) -> None:
|
||||
imgui.text(f"Session Cost: ${insights.get('session_cost', 0):.4f}")
|
||||
completed = insights.get('completed_tickets', 0)
|
||||
efficiency = insights.get('efficiency', 0)
|
||||
|
||||
def render_prior_session_view(app: App) -> None:
|
||||
with imscope.style_color(imgui.Col_.child_bg, theme.get_color("bubble_vendor")):
|
||||
if imgui.button("Exit Prior Session"): app.controller.cb_exit_prior_session(); app._comms_log_dirty = True
|
||||
@@ -3611,6 +3734,7 @@ def render_prior_session_view(app: App) -> None:
|
||||
with theme.ai_text_style():
|
||||
markdown_helper.render(content, context_id=f'prior_disc_{idx}')
|
||||
imgui.separator()
|
||||
|
||||
def render_thinking_indicator(app: App) -> None:
|
||||
is_thinking = app.ai_status in ['sending...', 'streaming...', 'running powershell...']
|
||||
if is_thinking:
|
||||
@@ -5406,128 +5530,3 @@ def render_mma_focus_selector(app: App) -> None:
|
||||
if app.ui_focus_agent and imgui.button("x##clear_focus"): app.ui_focus_agent = None
|
||||
|
||||
#endregion: MMA
|
||||
|
||||
def render_empty_context_modal(app: App) -> None:
|
||||
if app.show_empty_context_modal:
|
||||
imgui.open_popup("Empty Context Warning")
|
||||
app.show_empty_context_modal = False
|
||||
|
||||
if imgui.begin_popup_modal("Empty Context Warning", True, imgui.WindowFlags_.always_auto_resize)[0]:
|
||||
imgui.text_colored(theme.get_color("status_warning"), "WARNING: Empty Context Composition")
|
||||
imgui.text("You are attempting to generate a response without any files selected.")
|
||||
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()
|
||||
app._pending_generation_action = None
|
||||
imgui.close_current_popup()
|
||||
imgui.same_line()
|
||||
if imgui.button("Cancel", imgui.ImVec2(120, 0)):
|
||||
imgui.close_current_popup()
|
||||
imgui.end_popup()
|
||||
|
||||
def render_context_modals(app: App) -> None:
|
||||
render_empty_context_modal(app)
|
||||
render_add_context_files_modal(app)
|
||||
|
||||
if app.show_missing_files_modal:
|
||||
imgui.open_popup("Missing Files Warning")
|
||||
app.show_missing_files_modal = False
|
||||
|
||||
if imgui.begin_popup_modal("Missing Files Warning", True, imgui.WindowFlags_.always_auto_resize)[0]:
|
||||
imgui.text("The following files are missing from disk:")
|
||||
imgui.separator()
|
||||
imgui.begin_child("missing_files_list", imgui.ImVec2(0, 150), True)
|
||||
for f in app.missing_context_files:
|
||||
imgui.text_colored(theme.get_color("status_error"), f)
|
||||
imgui.end_child()
|
||||
imgui.separator()
|
||||
|
||||
if imgui.button("Save Anyway") or getattr(app, "_pending_save_anyway_click", False):
|
||||
app._pending_save_anyway_click = False
|
||||
name = app.target_context_preset_name
|
||||
preset_files = []
|
||||
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
|
||||
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)
|
||||
app.ui_new_context_preset_name = ""
|
||||
imgui.close_current_popup()
|
||||
|
||||
imgui.same_line()
|
||||
if imgui.button("Cancel"):
|
||||
imgui.close_current_popup()
|
||||
|
||||
imgui.end_popup()
|
||||
|
||||
render_ast_inspector_modal(app)
|
||||
|
||||
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', []))
|
||||
mask = tuple(sorted(getattr(f, 'ast_mask', {}).items()))
|
||||
files_state.append((p, vm, agg, slc, mask))
|
||||
screenshots_state = tuple(app.screenshots)
|
||||
return (tuple(files_state), screenshots_state)
|
||||
|
||||
def _check_auto_refresh_context_preview(app: App) -> None:
|
||||
current_state = _get_context_composition_state(app)
|
||||
if not hasattr(app, "_last_context_preview_state") or app._last_context_preview_state != current_state:
|
||||
app._last_context_preview_state = current_state
|
||||
if not any(getattr(f, 'auto_aggregate', False) for f in app.context_files) and not app.screenshots:
|
||||
app.context_preview_text = "# Context Composition Empty\n\nNo files or screenshots have been selected for aggregation."
|
||||
return
|
||||
|
||||
if getattr(app, "_is_generating_preview", False):
|
||||
app._pending_preview_refresh = True
|
||||
return
|
||||
|
||||
app._is_generating_preview = True
|
||||
def worker():
|
||||
try:
|
||||
app.controller.context_files = app.context_files
|
||||
res = app.controller._do_generate()
|
||||
app.context_preview_text = res[0]
|
||||
except Exception:
|
||||
app.context_preview_text = "Error generating context preview."
|
||||
finally:
|
||||
app._is_generating_preview = False
|
||||
if getattr(app, "_pending_preview_refresh", False):
|
||||
app._pending_preview_refresh = False
|
||||
# This will trigger again on next GUI frame because _last_context_preview_state
|
||||
# will be slightly behind if another change happened during the thread.
|
||||
# Or we just clear the state so it re-triggers.
|
||||
app._last_context_preview_state = None
|
||||
|
||||
import threading
|
||||
threading.Thread(target=worker, daemon=True).start()
|
||||
|
||||
def render_context_preview_window(app: App) -> None:
|
||||
_check_auto_refresh_context_preview(app)
|
||||
with imscope.window("Context Preview", app.show_windows["Context Preview"]) as (exp, opened):
|
||||
app.show_windows["Context Preview"] = bool(opened)
|
||||
if not opened:
|
||||
app.ui_separate_context_preview = False
|
||||
if exp:
|
||||
if imgui.button("Close"):
|
||||
app.show_windows["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)
|
||||
with imscope.child("ctx_preview_scroll", 0, 0, True):
|
||||
markdown_helper.render(app.context_preview_text, context_id="ctx_preview")
|
||||
|
||||
|
||||
Reference in New Issue
Block a user