gemini 3.1 fails

This commit is contained in:
2026-05-12 19:50:46 -04:00
parent 87aeee3322
commit ff1a9d77f7
2 changed files with 425 additions and 438 deletions
+389 -438
View File
@@ -15,7 +15,7 @@ import threading
import time
# from defer import defer
import tomli_w
# from contextlib import ExitStack
# from contextlib import ExitStack, nullcontext
import traceback
import typing
from pathlib import Path
@@ -605,53 +605,53 @@ class App:
def _render_thinking_trace(self, segments: list[dict], entry_index: int, is_standalone: bool = False) -> None:
if not segments:
return
imgui.push_style_color(imgui.Col_.child_bg, vec4(40, 35, 25, 180))
imgui.push_style_color(imgui.Col_.text, vec4(200, 200, 150))
imgui.indent()
with imscope.style_color(imgui.Col_.child_bg, vec4(40, 35, 25, 180)), \
imscope.style_color(imgui.Col_.text, vec4(200, 200, 150)):
imgui.indent()
show_content = True
if not is_standalone:
header_label = f"Monologue ({len(segments)} traces)###thinking_header_{entry_index}"
show_content = imgui.collapsing_header(header_label)
show_content = True
if not is_standalone:
header_label = f"Monologue ({len(segments)} traces)###thinking_header_{entry_index}"
show_content = imgui.collapsing_header(header_label)
if show_content:
h = 150 if is_standalone else 100
with imscope.child(f"thinking_content_{entry_index}", imgui.ImVec2(0, h), True):
for idx, seg in enumerate(segments):
content = seg.get("content", "")
marker = seg.get("marker", "thinking")
with imscope.id(f"think_{entry_index}_{idx}"):
imgui.text_colored(vec4(180, 150, 80), f"[{marker}]")
if self.ui_word_wrap:
imscope.text_wrap(imgui.get_content_region_avail().x)
imgui.text_colored(vec4(200, 200, 150), content)
else:
imgui.text_colored(vec4(200, 200, 150), content)
imgui.separator()
if show_content:
h = 150 if is_standalone else 100
with imscope.child(f"thinking_content_{entry_index}", imgui.ImVec2(0, h), True):
for idx, seg in enumerate(segments):
content = seg.get("content", "")
marker = seg.get("marker", "thinking")
with imscope.id(f"think_{entry_index}_{idx}"):
imgui.text_colored(vec4(180, 150, 80), f"[{marker}]")
if self.ui_word_wrap:
with imscope.text_wrap(imgui.get_content_region_avail().x):
imgui.text_colored(vec4(200, 200, 150), content)
else:
imgui.text_colored(vec4(200, 200, 150), content)
imgui.separator()
imgui.unindent()
imgui.pop_style_color(2)
imgui.unindent()
def _render_selectable_label(self, label: str, value: str, width: float = 0.0, multiline: bool = False, height: float = 0.0, color: Optional[imgui.ImVec4] = None) -> None:
imgui.push_id(label + str(hash(value)))
pops = 4
imgui.push_style_color(imgui.Col_.frame_bg, vec4(0, 0, 0, 0))
imgui.push_style_color(imgui.Col_.frame_bg_hovered, vec4(0, 0, 0, 0))
imgui.push_style_color(imgui.Col_.frame_bg_active, vec4(0, 0, 0, 0))
imgui.push_style_color(imgui.Col_.border, vec4(0, 0, 0, 0))
if color:
imgui.push_style_color(imgui.Col_.text, color)
pops += 1
imgui.push_style_var(imgui.StyleVar_.frame_border_size, 0.0)
imgui.push_style_var(imgui.StyleVar_.frame_padding, imgui.ImVec2(0, 0))
if multiline:
imgui.input_text_multiline("##" + label, value, imgui.ImVec2(width, height), imgui.InputTextFlags_.read_only)
else:
if width > 0: imgui.set_next_item_width(width)
imgui.input_text("##" + label, value, imgui.InputTextFlags_.read_only)
imgui.pop_style_color(pops)
imgui.pop_style_var(2)
imgui.pop_id()
with imscope.id(label + str(hash(value))):
with imscope.style_color(imgui.Col_.frame_bg, vec4(0, 0, 0, 0)), \
imscope.style_color(imgui.Col_.frame_bg_hovered, vec4(0, 0, 0, 0)), \
imscope.style_color(imgui.Col_.frame_bg_active, vec4(0, 0, 0, 0)), \
imscope.style_color(imgui.Col_.border, vec4(0, 0, 0, 0)):
with imscope.style_var(imgui.StyleVar_.frame_border_size, 0.0), \
imscope.style_var(imgui.StyleVar_.frame_padding, imgui.ImVec2(0, 0)):
if color:
with imscope.style_color(imgui.Col_.text, color):
if multiline:
imgui.input_text_multiline("##" + label, value, imgui.ImVec2(width, height), imgui.InputTextFlags_.read_only)
else:
if width > 0: imgui.set_next_item_width(width)
imgui.input_text("##" + label, value, imgui.InputTextFlags_.read_only)
else:
if multiline:
imgui.input_text_multiline("##" + label, value, imgui.ImVec2(width, height), imgui.InputTextFlags_.read_only)
else:
if width > 0: imgui.set_next_item_width(width)
imgui.input_text("##" + label, value, imgui.InputTextFlags_.read_only)
def _render_window_if_open(self, name: str, render_func: Callable[[], None], flag_condition: bool = True) -> None:
"""Helper to render a window only if its toggle is active."""
@@ -1220,34 +1220,30 @@ class App:
imgui.text_colored(c, "THINKING..."); imgui.same_line()
def _render_prior_session_view(self) -> None:
imgui.push_style_color(imgui.Col_.child_bg, vec4(50, 40, 20))
if imgui.button("Exit Prior Session"): self.controller.cb_exit_prior_session(); self._comms_log_dirty = True
imgui.separator()
with imscope.child("prior_scroll"):
clipper = imgui.ListClipper(); clipper.begin(len(self.prior_disc_entries))
while clipper.step():
for idx in range(clipper.display_start, clipper.display_end):
entry = self.prior_disc_entries[idx];
with imscope.id(f"prior_disc_{idx}"):
collapsed = entry.get("collapsed", False)
if imgui.button("+" if collapsed else "-"): entry["collapsed"] = not collapsed
imgui.same_line(); role, ts = entry.get("role", "??"), entry.get("ts", "")
imgui.text_colored(C_LBL, f"[{role}]")
if ts: imgui.same_line(); imgui.text_colored(vec4(160, 160, 160), str(ts))
content = entry.get("content", "")
if collapsed:
imgui.same_line(); preview = content.replace("\n", " ")[:80]
if len(content) > 80: preview += "..."
imgui.text_colored(vec4(180, 180, 180), preview)
else:
is_nerv = theme.is_nerv_active()
if is_nerv: imgui.push_style_color(imgui.Col_.text, vec4(80, 255, 80))
markdown_helper.render(content, context_id=f'prior_disc_{idx}')
if is_nerv: imgui.pop_style_color()
imgui.separator()
imgui.pop_style_color()
def _render_discussion_selector(self) -> None:
with imscope.style_color(imgui.Col_.child_bg, vec4(50, 40, 20)):
if imgui.button("Exit Prior Session"): self.controller.cb_exit_prior_session(); self._comms_log_dirty = True
imgui.separator()
with imscope.child("prior_scroll"):
clipper = imgui.ListClipper(); clipper.begin(len(self.prior_disc_entries))
while clipper.step():
for idx in range(clipper.display_start, clipper.display_end):
entry = self.prior_disc_entries[idx];
with imscope.id(f"prior_disc_{idx}"):
collapsed = entry.get("collapsed", False)
if imgui.button("+" if collapsed else "-"): entry["collapsed"] = not collapsed
imgui.same_line(); role, ts = entry.get("role", "??"), entry.get("ts", "")
imgui.text_colored(C_LBL, f"[{role}]")
if ts: imgui.same_line(); imgui.text_colored(vec4(160, 160, 160), str(ts))
content = entry.get("content", "")
if collapsed:
imgui.same_line(); preview = content.replace("\n", " ")[:80]
if len(content) > 80: preview += "..."
imgui.text_colored(vec4(180, 180, 180), preview)
else:
is_nerv = theme.is_nerv_active()
with imscope.style_color(imgui.Col_.text, vec4(80, 255, 80)) if is_nerv else nullcontext():
markdown_helper.render(content, context_id=f'prior_disc_{idx}')
imgui.separator()
if not imgui.collapsing_header("Discussions", imgui.TreeNodeFlags_.default_open): return
names = self._get_discussion_names(); grouped = {}
for name in names:
@@ -2204,11 +2200,12 @@ class App:
if not self.show_preset_manager_window and not is_embedded: return
if not is_embedded:
imgui.set_next_window_size(imgui.ImVec2(1000, 800), imgui.Cond_.first_use_ever)
opened, self.show_preset_manager_window = imgui.begin("Prompt Presets Manager", self.show_preset_manager_window)
if not opened:
imgui.end(); return
self._render_preset_manager_content(is_embedded=is_embedded)
if not is_embedded: imgui.end()
with imscope.window("Prompt Presets Manager", self.show_preset_manager_window) as (opened, visible):
self.show_preset_manager_window = visible
if opened:
self._render_preset_manager_content(is_embedded=is_embedded)
else:
self._render_preset_manager_content(is_embedded=is_embedded)
def _render_tool_preset_manager_content(self, is_embedded: bool = False) -> None:
avail = imgui.get_content_region_avail()
@@ -2382,16 +2379,16 @@ class App:
if not is_embedded:
if imgui.button("Close##tp", imgui.ImVec2(100, 0)): self.show_tool_preset_manager_window = False
imgui.end_table()
def _render_tool_preset_manager_window(self, is_embedded: bool = False) -> None:
if not self.show_tool_preset_manager_window and not is_embedded: return
if not is_embedded:
imgui.set_next_window_size(imgui.ImVec2(1000, 800), imgui.Cond_.first_use_ever)
opened, self.show_tool_preset_manager_window = imgui.begin("Tool Preset Manager", self.show_tool_preset_manager_window)
if not opened:
imgui.end(); return
self._render_tool_preset_manager_content(is_embedded=is_embedded)
if not is_embedded: imgui.end()
with imscope.window("Tool Preset Manager", self.show_tool_preset_manager_window) as (opened, visible):
self.show_tool_preset_manager_window = visible
if opened:
self._render_tool_preset_manager_content(is_embedded=is_embedded)
else:
self._render_preset_manager_content(is_embedded=is_embedded)
def _render_persona_editor_window(self, is_embedded: bool = False) -> None:
if not self.show_persona_editor_window and not is_embedded: return
@@ -2557,7 +2554,6 @@ class App:
if imgui.button("Close##pers", imgui.ImVec2(100, 0)):
self.show_persona_editor_window = False
imgui.end_table()
if not is_embedded: imgui.end()
def _render_projects_panel(self) -> None:
if self.perf_profiling_enabled: self.perf_monitor.start_component("_render_projects_panel")
@@ -2908,192 +2904,183 @@ class App:
[C: tests/test_log_management_ui.py:test_render_log_management_logic]
"""
if self.perf_profiling_enabled: self.perf_monitor.start_component("_render_log_management")
exp, opened = imgui.begin("Log Management", self.show_windows["Log Management"])
self.show_windows["Log Management"] = bool(opened)
if not exp:
imgui.end()
return
if self._log_registry is None:
self._log_registry = log_registry.LogRegistry(str(paths.get_logs_dir() / "log_registry.toml"))
else:
if imgui.button("Refresh Registry"):
self._log_registry = log_registry.LogRegistry(str(paths.get_logs_dir() / "log_registry.toml"))
imgui.same_line()
if imgui.button("Load Log"):
self.cb_load_prior_log()
imgui.same_line()
if imgui.button("Force Prune Logs"):
self.controller.event_queue.put("gui_task", {"action": "click", "item": "btn_prune_logs"})
registry = self._log_registry
sessions = registry.data
if imgui.begin_table("sessions_table", 7, imgui.TableFlags_.borders | imgui.TableFlags_.row_bg | imgui.TableFlags_.resizable):
imgui.table_setup_column("Session ID")
imgui.table_setup_column("Start Time")
imgui.table_setup_column("Star")
imgui.table_setup_column("Reason")
imgui.table_setup_column("Size (KB)")
imgui.table_setup_column("Msgs")
imgui.table_setup_column("Actions")
imgui.table_headers_row()
for session_id, s_data in sessions.items():
imgui.table_next_row()
imgui.table_next_column()
imgui.text(session_id)
imgui.table_next_column()
imgui.text(s_data.get("start_time", ""))
imgui.table_next_column()
whitelisted = s_data.get("whitelisted", False)
if whitelisted:
imgui.text_colored(vec4(255, 215, 0), "YES")
with imscope.window("Log Management", self.show_windows["Log Management"]) as (exp, opened):
self.show_windows["Log Management"] = bool(opened)
if exp:
if self._log_registry is None:
self._log_registry = log_registry.LogRegistry(str(paths.get_logs_dir() / "log_registry.toml"))
else:
imgui.text("NO")
metadata = s_data.get("metadata") or {}
imgui.table_next_column()
imgui.text(metadata.get("reason", ""))
imgui.table_next_column()
imgui.text(str(metadata.get("size_kb", "")))
imgui.table_next_column()
imgui.text(str(metadata.get("message_count", "")))
imgui.table_next_column()
if imgui.button(f"Load##{session_id}"):
self.cb_load_prior_log(s_data.get("path"))
if imgui.button("Refresh Registry"):
self._log_registry = log_registry.LogRegistry(str(paths.get_logs_dir() / "log_registry.toml"))
imgui.same_line()
if imgui.button("Load Log"):
self.cb_load_prior_log()
imgui.same_line()
if whitelisted:
if imgui.button(f"Unstar##{session_id}"):
registry.update_session_metadata(
session_id,
message_count=int(metadata.get("message_count") or 0),
errors=int(metadata.get("errors") or 0),
size_kb=int(metadata.get("size_kb") or 0),
whitelisted=False,
reason=str(metadata.get("reason") or "")
)
else:
if imgui.button(f"Star##{session_id}"):
registry.update_session_metadata(
session_id,
message_count=int(metadata.get("message_count") or 0),
errors=int(metadata.get("errors") or 0),
size_kb=int(metadata.get("size_kb") or 0),
whitelisted=True,
reason="Manually whitelisted"
)
imgui.end_table()
if imgui.button("Force Prune Logs"):
self.controller.event_queue.put("gui_task", {"action": "click", "item": "btn_prune_logs"})
registry = self._log_registry
sessions = registry.data
if imgui.begin_table("sessions_table", 7, imgui.TableFlags_.borders | imgui.TableFlags_.row_bg | imgui.TableFlags_.resizable):
imgui.table_setup_column("Session ID")
imgui.table_setup_column("Start Time")
imgui.table_setup_column("Star")
imgui.table_setup_column("Reason")
imgui.table_setup_column("Size (KB)")
imgui.table_setup_column("Msgs")
imgui.table_setup_column("Actions")
imgui.table_headers_row()
for session_id, s_data in sessions.items():
imgui.table_next_row()
imgui.table_next_column()
imgui.text(session_id)
imgui.table_next_column()
imgui.text(s_data.get("start_time", ""))
imgui.table_next_column()
whitelisted = s_data.get("whitelisted", False)
if whitelisted:
imgui.text_colored(vec4(255, 215, 0), "YES")
else:
imgui.text("NO")
metadata = s_data.get("metadata") or {}
imgui.table_next_column()
imgui.text(metadata.get("reason", ""))
imgui.table_next_column()
imgui.text(str(metadata.get("size_kb", "")))
imgui.table_next_column()
imgui.text(str(metadata.get("message_count", "")))
imgui.table_next_column()
if imgui.button(f"Load##{session_id}"):
self.cb_load_prior_log(s_data.get("path"))
imgui.same_line()
if whitelisted:
if imgui.button(f"Unstar##{session_id}"):
registry.update_session_metadata(
session_id,
message_count=int(metadata.get("message_count") or 0),
errors=int(metadata.get("errors") or 0),
size_kb=int(metadata.get("size_kb") or 0),
whitelisted=False,
reason=str(metadata.get("reason") or "")
)
else:
if imgui.button(f"Star##{session_id}"):
registry.update_session_metadata(
session_id,
message_count=int(metadata.get("message_count") or 0),
errors=int(metadata.get("errors") or 0),
size_kb=int(metadata.get("size_kb") or 0),
whitelisted=True,
reason="Manually whitelisted"
)
imgui.end_table()
if self.perf_profiling_enabled: self.perf_monitor.end_component("_render_log_management")
imgui.end()
def _render_diagnostics_panel(self) -> None:
if self.perf_profiling_enabled: self.perf_monitor.start_component("_render_diagnostics_panel")
exp, opened = imgui.begin("Diagnostics", self.show_windows.get("Diagnostics", False))
self.show_windows["Diagnostics"] = bool(opened)
if not exp:
imgui.end()
if self.perf_profiling_enabled: self.perf_monitor.end_component("_render_diagnostics_panel")
return
metrics = self.perf_monitor.get_metrics()
imgui.text("Performance Telemetry")
imgui.same_line()
_, self.perf_profiling_enabled = imgui.checkbox("Enable Profiling", self.perf_profiling_enabled)
imgui.separator()
if imgui.begin_table("perf_table", 3, imgui.TableFlags_.borders_inner_h):
imgui.table_setup_column("Metric")
imgui.table_setup_column("Value")
imgui.table_setup_column("Graph")
imgui.table_headers_row()
for label, key, format_str in [
("FPS", "fps", "%.1f"),
("Frame Time (ms)", "frame_time_ms", "%.2f"),
("CPU %", "cpu_percent", "%.1f"),
("Input Lag (ms)", "input_lag_ms", "%.1f")
]:
imgui.table_next_row()
imgui.table_next_column()
imgui.text(label)
imgui.table_next_column()
if key == "fps":
avg_val = imgui.get_io().framerate
else:
avg_val = metrics.get(f"{key}_avg", metrics.get(key, 0.0))
imgui.text(format_str % avg_val)
imgui.table_next_column()
self.perf_show_graphs.setdefault(key, False)
_, self.perf_show_graphs[key] = imgui.checkbox(f"##g_{key}", self.perf_show_graphs[key])
imgui.end_table()
if self.perf_profiling_enabled:
imgui.separator()
imgui.text("Detailed Component Timings (Moving Average)")
if imgui.begin_table("comp_timings", 6, imgui.TableFlags_.borders):
imgui.table_setup_column("Component")
imgui.table_setup_column("Avg (ms)")
imgui.table_setup_column("Count")
imgui.table_setup_column("Max (ms)")
imgui.table_setup_column("Min (ms)")
imgui.table_setup_column("Graph")
imgui.table_headers_row()
for key, val in metrics.items():
if key.startswith("time_") and key.endswith("_ms") and not key.endswith("_avg"):
comp_name = key[5:-3]
avg_val = metrics.get(f"{key}_avg", val)
count = int(metrics.get(f"count_{comp_name}", 0))
max_val = metrics.get(f"max_{comp_name}_ms", 0.0)
min_val = metrics.get(f"min_{comp_name}_ms", 0.0)
with imscope.window("Diagnostics", self.show_windows.get("Diagnostics", False)) as (exp, opened):
self.show_windows["Diagnostics"] = bool(opened)
if exp:
metrics = self.perf_monitor.get_metrics()
imgui.text("Performance Telemetry")
imgui.same_line()
_, self.perf_profiling_enabled = imgui.checkbox("Enable Profiling", self.perf_profiling_enabled)
imgui.separator()
if imgui.begin_table("perf_table", 3, imgui.TableFlags_.borders_inner_h):
imgui.table_setup_column("Metric")
imgui.table_setup_column("Value")
imgui.table_setup_column("Graph")
imgui.table_headers_row()
for label, key, format_str in [
("FPS", "fps", "%.1f"),
("Frame Time (ms)", "frame_time_ms", "%.2f"),
("CPU %", "cpu_percent", "%.1f"),
("Input Lag (ms)", "input_lag_ms", "%.1f")
]:
imgui.table_next_row()
imgui.table_next_column()
imgui.text(comp_name)
imgui.text(label)
imgui.table_next_column()
if avg_val > 10.0:
imgui.text_colored(imgui.ImVec4(1.0, 0.2, 0.2, 1.0), f"{avg_val:.2f}")
if key == "fps":
avg_val = imgui.get_io().framerate
else:
imgui.text(f"{avg_val:.2f}")
avg_val = metrics.get(f"{key}_avg", metrics.get(key, 0.0))
imgui.text(format_str % avg_val)
imgui.table_next_column()
imgui.text(f"{count}")
imgui.table_next_column()
imgui.text(f"{max_val:.2f}")
imgui.table_next_column()
imgui.text(f"{min_val:.2f}")
imgui.table_next_column()
self.perf_show_graphs.setdefault(comp_name, False)
_, self.perf_show_graphs[comp_name] = imgui.checkbox(f"##g_{comp_name}", self.perf_show_graphs[comp_name])
imgui.end_table()
self.perf_show_graphs.setdefault(key, False)
_, self.perf_show_graphs[key] = imgui.checkbox(f"##g_{key}", self.perf_show_graphs[key])
imgui.end_table()
imgui.separator()
imgui.text("Performance Graphs")
for key, show in self.perf_show_graphs.items():
if show:
imgui.text(f"History: {key}")
hist_data = self.perf_monitor.get_history(key)
if hist_data:
import numpy as np
imgui.plot_lines(f"##plot_{key}", np.array(hist_data, dtype=np.float32), graph_size=imgui.ImVec2(-1, 60))
else:
imgui.text_disabled(f"(no history data for {key})")
if self.perf_profiling_enabled:
imgui.separator()
imgui.text("Detailed Component Timings (Moving Average)")
if imgui.begin_table("comp_timings", 6, imgui.TableFlags_.borders):
imgui.table_setup_column("Component")
imgui.table_setup_column("Avg (ms)")
imgui.table_setup_column("Count")
imgui.table_setup_column("Max (ms)")
imgui.table_setup_column("Min (ms)")
imgui.table_setup_column("Graph")
imgui.table_headers_row()
for key, val in metrics.items():
if key.startswith("time_") and key.endswith("_ms") and not key.endswith("_avg"):
comp_name = key[5:-3]
avg_val = metrics.get(f"{key}_avg", val)
count = int(metrics.get(f"count_{comp_name}", 0))
max_val = metrics.get(f"max_{comp_name}_ms", 0.0)
min_val = metrics.get(f"min_{comp_name}_ms", 0.0)
imgui.table_next_row()
imgui.table_next_column()
imgui.text(comp_name)
imgui.table_next_column()
if avg_val > 10.0:
imgui.text_colored(imgui.ImVec4(1.0, 0.2, 0.2, 1.0), f"{avg_val:.2f}")
else:
imgui.text(f"{avg_val:.2f}")
imgui.table_next_column()
imgui.text(f"{count}")
imgui.table_next_column()
imgui.text(f"{max_val:.2f}")
imgui.table_next_column()
imgui.text(f"{min_val:.2f}")
imgui.table_next_column()
self.perf_show_graphs.setdefault(comp_name, False)
_, self.perf_show_graphs[comp_name] = imgui.checkbox(f"##g_{comp_name}", self.perf_show_graphs[comp_name])
imgui.end_table()
imgui.separator()
imgui.text("Diagnostic Log")
if imgui.begin_table("diag_log_table", 3, imgui.TableFlags_.borders | imgui.TableFlags_.row_bg | imgui.TableFlags_.resizable):
imgui.table_setup_column("Timestamp", imgui.TableColumnFlags_.width_fixed, 150)
imgui.table_setup_column("Type", imgui.TableColumnFlags_.width_fixed, 100)
imgui.table_setup_column("Message")
imgui.table_headers_row()
for entry in reversed(self.controller.diagnostic_log):
imgui.table_next_row()
imgui.table_next_column()
imgui.text(entry.get("ts", ""))
imgui.table_next_column()
imgui.text(entry.get("type", ""))
imgui.table_next_column()
imgui.text_wrapped(entry.get("message", ""))
imgui.end_table()
imgui.separator()
imgui.text("Performance Graphs")
for key, show in self.perf_show_graphs.items():
if show:
imgui.text(f"History: {key}")
hist_data = self.perf_monitor.get_history(key)
if hist_data:
import numpy as np
imgui.plot_lines(f"##plot_{key}", np.array(hist_data, dtype=np.float32), graph_size=imgui.ImVec2(-1, 60))
else:
imgui.text_disabled(f"(no history data for {key})")
imgui.separator()
imgui.text("Diagnostic Log")
if imgui.begin_table("diag_log_table", 3, imgui.TableFlags_.borders | imgui.TableFlags_.row_bg | imgui.TableFlags_.resizable):
imgui.table_setup_column("Timestamp", imgui.TableColumnFlags_.width_fixed, 150)
imgui.table_setup_column("Type", imgui.TableColumnFlags_.width_fixed, 100)
imgui.table_setup_column("Message")
imgui.table_headers_row()
for entry in reversed(self.controller.diagnostic_log):
imgui.table_next_row()
imgui.table_next_column()
imgui.text(entry.get("ts", ""))
imgui.table_next_column()
imgui.text(entry.get("type", ""))
imgui.table_next_column()
imgui.text_wrapped(entry.get("message", ""))
imgui.end_table()
if self.perf_profiling_enabled: self.perf_monitor.end_component("_render_diagnostics_panel")
imgui.end()
def _render_discussion_tab(self) -> None:
imgui.begin_child("HistoryChild", size=(0, -self.ui_discussion_split_h))
@@ -3215,118 +3202,116 @@ class App:
grouped_files = aggregate.group_files_by_dir(self.context_files)
if imgui.begin_table("ctx_comp_table", 2, imgui.TableFlags_.resizable | imgui.TableFlags_.borders):
imgui.table_setup_column("File", imgui.TableColumnFlags_.width_stretch)
imgui.table_setup_column("Flags", imgui.TableColumnFlags_.width_fixed, 200)
imgui.table_headers_row()
file_indices = {id(f): idx for idx, f in enumerate(self.context_files)}
for dir_name, g_files in grouped_files.items():
imgui.table_next_row()
imgui.table_set_column_index(0)
is_open = imgui.tree_node_ex(f"{dir_name}##dir_{dir_name}", imgui.TreeNodeFlags_.default_open)
imgui.table_set_column_index(1)
if is_open:
for f_item in g_files:
i = file_indices[id(f_item)]
imgui.table_next_row()
imgui.table_set_column_index(0)
# Checkbox for selection
f_path = f_item.path if hasattr(f_item, "path") else str(f_item)
is_sel = f_path in self.ui_selected_context_files
changed_sel, is_sel = imgui.checkbox(f"##sel{i}", is_sel)
if changed_sel:
if imgui.get_io().key_shift and self._last_selected_context_index != -1:
start = min(self._last_selected_context_index, i)
end = max(self._last_selected_context_index, i)
for idx in range(start, end + 1):
item = self.context_files[idx]
item_path = item.path if hasattr(item, "path") else str(item)
if is_sel:
self.ui_selected_context_files.add(item_path)
else:
self.ui_selected_context_files.discard(item_path)
else:
if is_sel:
self.ui_selected_context_files.add(f_path)
else:
self.ui_selected_context_files.discard(f_path)
self._last_selected_context_index = i
imgui.same_line()
mtime = os.path.getmtime(f_path) if os.path.exists(f_path) else 0
cache_key = f"{f_path}_{mtime}"
stats = self._file_stats_cache.get(cache_key, {"lines": 0, "ast_elements": 0})
f_name = os.path.basename(f_path)
imgui.text(f"{f_name} (L: {stats.get('lines', 0)}, AST: {stats.get('ast_elements', 0)})")
if f_path.lower().endswith(('.c', '.cpp', '.h', '.hpp', '.cxx', '.cc')):
imgui.same_line()
if imgui.button(f"[Inspect]##{i}"):
self.ui_inspecting_ast_file = f_item
self._show_ast_inspector = True
imgui.same_line()
if imgui.button(f"[Slices]##{i}"):
self.ui_editing_slices_file = f_item
f_path = f_item.path if hasattr(f_item, "path") else str(f_item)
self.text_viewer_title = f"Slices: {f_path}"
try:
self.text_viewer_content = mcp_client.read_file(f_path)
except Exception as e:
self.text_viewer_content = f"Error reading file: {e}"
self.text_viewer_type = 'cpp' if f_path.endswith(('.cpp', '.hpp', '.h')) else 'python' if f_path.endswith('.py') else 'text'
self.show_text_viewer = True
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("Flags", imgui.TableColumnFlags_.width_fixed, 200)
imgui.table_headers_row()
file_indices = {id(f): idx for idx, f in enumerate(self.context_files)}
for dir_name, g_files in grouped_files.items():
imgui.table_next_row()
imgui.table_set_column_index(0)
with imscope.tree_node_ex(f"{dir_name}##dir_{dir_name}", imgui.TreeNodeFlags_.default_open) as is_open:
imgui.table_set_column_index(1)
if not hasattr(f_item, "view_mode"):
f_item.view_mode = "summary"
view_modes = ["full", "summary", "skeleton", "outline", "masked", "none"]
try:
current_idx = view_modes.index(f_item.view_mode)
except ValueError:
current_idx = 1
f_item.view_mode = "summary"
imgui.set_next_item_width(120)
changed_vm, new_idx = imgui.combo(f"##vm{i}", current_idx, view_modes)
if changed_vm:
f_item.view_mode = view_modes[new_idx]
imgui.same_line()
if imgui.button(f"[Save]##vpsave{i}"):
imgui.open_popup(f"save_vp_popup{i}")
if imgui.begin_popup(f"save_vp_popup{i}"):
imgui.text("Preset Name:")
changed_pname, self.ui_new_vp_name = imgui.input_text(f"##pname{i}", self.ui_new_vp_name)
if imgui.button("OK"):
if self.ui_new_vp_name.strip():
self.controller._cb_save_view_preset(self.ui_new_vp_name.strip(), f_item)
self.ui_new_vp_name = ""
imgui.close_current_popup()
imgui.end_popup()
if is_open:
for f_item in g_files:
i = file_indices[id(f_item)]
imgui.table_next_row()
imgui.table_set_column_index(0)
# Checkbox for selection
f_path = f_item.path if hasattr(f_item, "path") else str(f_item)
is_sel = f_path in self.ui_selected_context_files
changed_sel, is_sel = imgui.checkbox(f"##sel{i}", is_sel)
if changed_sel:
if imgui.get_io().key_shift and self._last_selected_context_index != -1:
start = min(self._last_selected_context_index, i)
end = max(self._last_selected_context_index, i)
for idx in range(start, end + 1):
item = self.context_files[idx]
item_path = item.path if hasattr(item, "path") else str(item)
if is_sel:
self.ui_selected_context_files.add(item_path)
else:
self.ui_selected_context_files.discard(item_path)
else:
if is_sel:
self.ui_selected_context_files.add(f_path)
else:
self.ui_selected_context_files.discard(f_path)
self._last_selected_context_index = i
imgui.same_line()
mtime = os.path.getmtime(f_path) if os.path.exists(f_path) else 0
cache_key = f"{f_path}_{mtime}"
stats = self._file_stats_cache.get(cache_key, {"lines": 0, "ast_elements": 0})
f_name = os.path.basename(f_path)
imgui.text(f"{f_name} (L: {stats.get('lines', 0)}, AST: {stats.get('ast_elements', 0)})")
imgui.same_line()
if imgui.button(f"[Load]##vpload{i}"):
imgui.open_popup(f"load_vp_popup{i}")
if imgui.begin_popup(f"load_vp_popup{i}"):
vp_names = sorted([vp.name for vp in self.controller.view_presets])
if not vp_names:
imgui.text("No presets saved.")
for vp_name in vp_names:
if imgui.selectable(vp_name):
self.controller._cb_apply_view_preset(vp_name, f_item)
imgui.close_current_popup()
imgui.end_popup()
if hasattr(f_item, "custom_slices") and f_item.custom_slices:
imgui.same_line()
imgui.text_colored(imgui.ImVec4(1.0, 0.5, 0.0, 1.0), "[Slices Active]")
imgui.tree_pop()
imgui.end_table()
if f_path.lower().endswith(('.c', '.cpp', '.h', '.hpp', '.cxx', '.cc')):
imgui.same_line()
if imgui.button(f"[Inspect]##{i}"):
self.ui_inspecting_ast_file = f_item
self._show_ast_inspector = True
imgui.same_line()
if imgui.button(f"[Slices]##{i}"):
self.ui_editing_slices_file = f_item
f_path = f_item.path if hasattr(f_item, "path") else str(f_item)
self.text_viewer_title = f"Slices: {f_path}"
try:
self.text_viewer_content = mcp_client.read_file(f_path)
except Exception as e:
self.text_viewer_content = f"Error reading file: {e}"
self.text_viewer_type = 'cpp' if f_path.endswith(('.cpp', '.hpp', '.h')) else 'python' if f_path.endswith('.py') else 'text'
self.show_text_viewer = True
imgui.table_set_column_index(1)
if not hasattr(f_item, "view_mode"):
f_item.view_mode = "summary"
view_modes = ["full", "summary", "skeleton", "outline", "masked", "none"]
try:
current_idx = view_modes.index(f_item.view_mode)
except ValueError:
current_idx = 1
f_item.view_mode = "summary"
imgui.set_next_item_width(120)
changed_vm, new_idx = imgui.combo(f"##vm{i}", current_idx, view_modes)
if changed_vm:
f_item.view_mode = view_modes[new_idx]
imgui.same_line()
if imgui.button(f"[Save]##vpsave{i}"):
imgui.open_popup(f"save_vp_popup{i}")
if imgui.begin_popup(f"save_vp_popup{i}"):
imgui.text("Preset Name:")
changed_pname, self.ui_new_vp_name = imgui.input_text(f"##pname{i}", self.ui_new_vp_name)
if imgui.button("OK"):
if self.ui_new_vp_name.strip():
self.controller._cb_save_view_preset(self.ui_new_vp_name.strip(), f_item)
self.ui_new_vp_name = ""
imgui.close_current_popup()
imgui.end_popup()
imgui.same_line()
if imgui.button(f"[Load]##vpload{i}"):
imgui.open_popup(f"load_vp_popup{i}")
if imgui.begin_popup(f"load_vp_popup{i}"):
vp_names = sorted([vp.name for vp in self.controller.view_presets])
if not vp_names:
imgui.text("No presets saved.")
for vp_name in vp_names:
if imgui.selectable(vp_name):
self.controller._cb_apply_view_preset(vp_name, f_item)
imgui.close_current_popup()
imgui.end_popup()
if hasattr(f_item, "custom_slices") and f_item.custom_slices:
imgui.same_line()
imgui.text_colored(imgui.ImVec4(1.0, 0.5, 0.0, 1.0), "[Slices Active]")
# Context Composition collasping header
imgui.separator()
@@ -4078,53 +4063,47 @@ def hello():
self._handle_reset_session()
if self.perf_profiling_enabled: self.perf_monitor.end_component("_render_message_panel")
def _render_response_panel(self) -> None:
if self.perf_profiling_enabled: self.perf_monitor.start_component("_render_response_panel")
if self._trigger_blink:
self._trigger_blink = False
self._is_blinking = True
self._blink_start_time = time.time()
try:
imgui.set_window_focus("Response") # type: ignore[call-arg]
except:
pass
is_blinking = False
if self._is_blinking:
elapsed = time.time() - self._blink_start_time
if elapsed > 1.5:
self._is_blinking = False
else:
is_blinking = True
val = math.sin(elapsed * 8 * math.pi)
alpha = 50/255 if val > 0 else 0
imgui.push_style_color(imgui.Col_.frame_bg, vec4(0, 255, 0, alpha))
imgui.push_style_color(imgui.Col_.child_bg, vec4(0, 255, 0, alpha))
# --- Always Render Content ---
imgui.begin_child("response_scroll_area", imgui.ImVec2(0, -40), True)
is_nerv = theme.is_nerv_active()
if is_nerv: imgui.push_style_color(imgui.Col_.text, vec4(80, 255, 80))
segments, parsed_response = thinking_parser.parse_thinking_trace(self.ai_response)
if segments:
self._render_thinking_trace([{"content": s.content, "marker": s.marker} for s in segments], 9999)
markdown_helper.render(parsed_response, context_id="response")
if is_nerv: imgui.pop_style_color()
imgui.end_child()
imgui.separator()
if imgui.button("-> History"):
if self.ai_response:
segments, response = thinking_parser.parse_thinking_trace(self.ai_response)
entry = {"role": "AI", "content": response, "collapsed": True, "ts": project_manager.now_ts()}
if segments:
entry["thinking_segments"] = [{"content": s.content, "marker": s.marker} for s in segments]
self.disc_entries.append(entry)
if is_blinking:
imgui.pop_style_color(2)
if self.perf_profiling_enabled: self.perf_monitor.end_component("_render_response_panel")
def _render_response_panel(self) -> None:
if self.perf_profiling_enabled: self.perf_monitor.start_component("_render_response_panel")
if self._trigger_blink:
self._trigger_blink = False
self._is_blinking = True
self._blink_start_time = time.time()
try:
imgui.set_window_focus("Response") # type: ignore[call-arg]
except:
pass
is_blinking = False
blink_color = vec4(0, 0, 0, 0)
if self._is_blinking:
elapsed = time.time() - self._blink_start_time
if elapsed > 1.5:
self._is_blinking = False
else:
is_blinking = True
val = math.sin(elapsed * 8 * math.pi)
alpha = 50/255 if val > 0 else 0
blink_color = vec4(0, 255, 0, alpha)
with imscope.style_color(imgui.Col_.frame_bg, blink_color) if is_blinking else nullcontext():
with imscope.style_color(imgui.Col_.child_bg, blink_color) if is_blinking else nullcontext():
with imscope.child("response_scroll_area", imgui.ImVec2(0, -40), True):
is_nerv = theme.is_nerv_active()
with imscope.style_color(imgui.Col_.text, vec4(80, 255, 80)) if is_nerv else nullcontext():
segments, parsed_response = thinking_parser.parse_thinking_trace(self.ai_response)
if segments:
self._render_thinking_trace([{"content": s.content, "marker": s.marker} for s in segments], 9999)
markdown_helper.render(parsed_response, context_id="response")
imgui.separator()
if imgui.button("-> History"):
if self.ai_response:
segments, response = thinking_parser.parse_thinking_trace(self.ai_response)
entry = {"role": "AI", "content": response, "collapsed": True, "ts": project_manager.now_ts()}
if segments:
entry["thinking_segments"] = [{"content": s.content, "marker": s.marker} for s in segments]
self.disc_entries.append(entry)
if self.perf_profiling_enabled: self.perf_monitor.end_component("_render_response_panel")
def _render_external_tools_panel(self) -> None:
if self.perf_profiling_enabled: self.perf_monitor.start_component("_render_external_tools_panel")
@@ -5188,34 +5167,6 @@ def hello():
imgui.end()
if self.perf_profiling_enabled: self.perf_monitor.end_component("_render_theme_panel")
def _render_prior_session_view(self) -> None: imgui.push_style_color(imgui.Col_.child_bg, vec4(50, 40, 20))
if imgui.button("Exit Prior Session"): self.controller.cb_exit_prior_session(); self._comms_log_dirty = True
imgui.separator()
with imscope.child("prior_scroll"):
clipper = imgui.ListClipper(); clipper.begin(len(self.prior_disc_entries))
while clipper.step():
for idx in range(clipper.display_start, clipper.display_end):
entry = self.prior_disc_entries[idx];
with imscope.id(f"prior_disc_{idx}"):
collapsed = entry.get("collapsed", False)
if imgui.button("+" if collapsed else "-"): entry["collapsed"] = not collapsed
imgui.same_line(); role, ts = entry.get("role", "??"), entry.get("ts", "")
imgui.text_colored(C_LBL, f"[{role}]")
if ts: imgui.same_line(); imgui.text_colored(vec4(160, 160, 160), str(ts))
content = entry.get("content", "")
if collapsed:
imgui.same_line(); preview = content.replace("\n", " ")[:80]
if len(content) > 80: preview += "..."
imgui.text_colored(vec4(180, 180, 180), preview)
else:
is_nerv = theme.is_nerv_active()
if is_nerv: imgui.push_style_color(imgui.Col_.text, vec4(80, 255, 80))
markdown_helper.render(content, context_id=f'prior_disc_{idx}')
if is_nerv: imgui.pop_style_color()
imgui.separator()
imgui.pop_style_color()
def _render_discussion_selector(self) -> None:
if not imgui.collapsing_header("Discussions", imgui.TreeNodeFlags_.default_open): return
names = self._get_discussion_names(); grouped = {}
for name in names:
+36
View File
@@ -160,3 +160,39 @@ class _ScopeTabItem:
if self._expanded:
imgui.end_tab_item()
return False
def style_color(col: int, val: Any): return _ScopeStyleColor(col, val)
class _ScopeStyleColor:
def __init__(self, col: int, val: Any):
self._col = col
self._val = val
def __enter__(self):
imgui.push_style_color(self._col, self._val)
def __exit__(self, *args):
imgui.pop_style_color()
return False
def style_var(var: int, val: Any): return _ScopeStyleVar(var, val)
class _ScopeStyleVar:
def __init__(self, var: int, val: Any):
self._var = var
self._val = val
def __enter__(self):
imgui.push_style_var(self._var, self._val)
def __exit__(self, *args):
imgui.pop_style_var()
return False
def tree_node_ex(label: str, flags: int = 0): return _ScopeTreeNodeEx(label, flags)
class _ScopeTreeNodeEx:
def __init__(self, label: str, flags: int):
self._label = label
self._flags = flags
self._opened = False
def __enter__(self):
self._opened = imgui.tree_node_ex(self._label, self._flags)
return self._opened
def __exit__(self, *args):
if self._opened:
imgui.tree_pop()
return False