Private
Public Access
reading throuogh gui_2.py (still reading)
This commit is contained in:
+164
-273
@@ -369,6 +369,7 @@ class App:
|
|||||||
self.controller.save_context_preset(preset)
|
self.controller.save_context_preset(preset)
|
||||||
self.ui_new_context_preset_name = ""
|
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._predefined_callbacks['get_app_debug_info'] = lambda: self.app_debug_info
|
||||||
self.controller._gettable_fields ['app_debug_info'] = '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
|
self.controller._predefined_callbacks['save_context_preset_force'] = _save_context_preset_force
|
||||||
@@ -541,6 +542,7 @@ class App:
|
|||||||
self.context_files = [item]
|
self.context_files = [item]
|
||||||
self.screenshots = ['test.png']
|
self.screenshots = ['test.png']
|
||||||
self.save_context_preset(name)
|
self.save_context_preset(name)
|
||||||
|
|
||||||
def _handle_approve_ask(self) -> None:
|
def _handle_approve_ask(self) -> None:
|
||||||
"""UI-level wrapper for approving a pending tool execution ask."""
|
"""UI-level wrapper for approving a pending tool execution ask."""
|
||||||
self.controller._handle_approve_ask()
|
self.controller._handle_approve_ask()
|
||||||
@@ -957,15 +959,12 @@ class App:
|
|||||||
"""Re-applies the next snapshot in the history stack (forward navigation).
|
"""Re-applies the next snapshot in the history stack (forward navigation).
|
||||||
SSDL Shape: `[I:snapshot] -> [B:history] => [I:state]`
|
SSDL Shape: `[I:snapshot] -> [B:history] => [I:state]`
|
||||||
"""
|
"""
|
||||||
sys.stderr.write(f"[DEBUG History] _handle_redo called. can_redo={self.history.can_redo}\n")
|
sys.stderr.write(f"[DEBUG History] _handle_redo called. can_redo={self.history.can_redo}\n"); sys.stderr.flush()
|
||||||
sys.stderr.flush()
|
if not self.history.can_redo: return
|
||||||
if not self.history.can_redo:
|
|
||||||
return
|
|
||||||
current = self._take_snapshot()
|
current = self._take_snapshot()
|
||||||
entry = self.history.redo(current, "Redo Action")
|
entry = self.history.redo(current, "Redo Action")
|
||||||
if entry:
|
if entry:
|
||||||
sys.stderr.write(f"[DEBUG History] Redoing to: {entry.description}\n")
|
sys.stderr.write(f"[DEBUG History] Redoing to: {entry.description}\n"); sys.stderr.flush()
|
||||||
sys.stderr.flush()
|
|
||||||
self._apply_snapshot(entry.state)
|
self._apply_snapshot(entry.state)
|
||||||
|
|
||||||
def shutdown(self) -> None:
|
def shutdown(self) -> None:
|
||||||
@@ -973,6 +972,7 @@ class App:
|
|||||||
forces a save of dirty registries/caches, and terminates the active thread pools.
|
forces a save of dirty registries/caches, and terminates the active thread pools.
|
||||||
SSDL Shape: `[I:save_ini] -> [I:controller_shutdown]`
|
SSDL Shape: `[I:save_ini] -> [I:controller_shutdown]`
|
||||||
"""
|
"""
|
||||||
|
#Note(Ed): Exception(Thirdparty)
|
||||||
try:
|
try:
|
||||||
if hasattr(self, 'runner_params') and self.runner_params.ini_filename:
|
if hasattr(self, 'runner_params') and self.runner_params.ini_filename:
|
||||||
imgui.save_ini_settings_to_disk(self.runner_params.ini_filename)
|
imgui.save_ini_settings_to_disk(self.runner_params.ini_filename)
|
||||||
@@ -1218,7 +1218,7 @@ class App:
|
|||||||
win32gui.SendMessage(hwnd, win32con.WM_NCLBUTTONDOWN, win32con.HTCAPTION, 0)
|
win32gui.SendMessage(hwnd, win32con.WM_NCLBUTTONDOWN, win32con.HTCAPTION, 0)
|
||||||
|
|
||||||
imgui.push_style_color(imgui.Col_.button, imgui.ImVec4(0, 0, 0, 0))
|
imgui.push_style_color(imgui.Col_.button, imgui.ImVec4(0, 0, 0, 0))
|
||||||
#Note(Ed): Thirdparty Exception
|
#Note(Ed): Exception(Thirdparty)
|
||||||
try: is_max = win32gui.GetWindowPlacement(hwnd)[1] == win32con.SW_SHOWMAXIMIZED
|
try: is_max = win32gui.GetWindowPlacement(hwnd)[1] == win32con.SW_SHOWMAXIMIZED
|
||||||
except Exception: is_max = False
|
except Exception: is_max = False
|
||||||
# Explicitly set Y to 0 and match button height to bar height for perfect alignment
|
# Explicitly set Y to 0 and match button height to bar height for perfect alignment
|
||||||
@@ -1293,8 +1293,7 @@ class App:
|
|||||||
root = hide_tk_root()
|
root = hide_tk_root()
|
||||||
path = filedialog.askdirectory(title='Select Session Directory', initialdir=str(paths.get_logs_dir()))
|
path = filedialog.askdirectory(title='Select Session Directory', initialdir=str(paths.get_logs_dir()))
|
||||||
root.destroy()
|
root.destroy()
|
||||||
if path:
|
if path: self.controller.cb_load_prior_log(path)
|
||||||
self.controller.cb_load_prior_log(path)
|
|
||||||
|
|
||||||
def _set_external_editor_default(self, editor_name: str) -> None:
|
def _set_external_editor_default(self, editor_name: str) -> None:
|
||||||
from src import models
|
from src import models
|
||||||
@@ -1326,6 +1325,8 @@ class App:
|
|||||||
mcp_client.configure([{"path": abs_path}], [proj_dir] if proj_dir else None)
|
mcp_client.configure([{"path": abs_path}], [proj_dir] if proj_dir else None)
|
||||||
|
|
||||||
f_path_lower = f_item.path.lower()
|
f_path_lower = f_item.path.lower()
|
||||||
|
|
||||||
|
#TODO(Ed): Exception(Review)
|
||||||
try:
|
try:
|
||||||
if f_path_lower.endswith('.py'): outline = mcp_client.py_get_code_outline(abs_path)
|
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(('.c', '.h')): outline = mcp_client.ts_c_get_code_outline(abs_path)
|
||||||
@@ -1342,6 +1343,7 @@ class App:
|
|||||||
text = f.read()
|
text = f.read()
|
||||||
except Exception:
|
except Exception:
|
||||||
return
|
return
|
||||||
|
#TODO(Ed): Exception(Review)
|
||||||
try:
|
try:
|
||||||
from src.fuzzy_anchor import FuzzyAnchor
|
from src.fuzzy_anchor import FuzzyAnchor
|
||||||
except ImportError:
|
except ImportError:
|
||||||
@@ -1352,10 +1354,8 @@ class App:
|
|||||||
e_line = int(e_str)
|
e_line = int(e_str)
|
||||||
if any(s.get('start_line') == s_line and s.get('end_line') == e_line for s in f_item.custom_slices):
|
if any(s.get('start_line') == s_line and s.get('end_line') == e_line for s in f_item.custom_slices):
|
||||||
continue
|
continue
|
||||||
if FuzzyAnchor:
|
if FuzzyAnchor: slice_data = FuzzyAnchor.create_slice(text, s_line, e_line)
|
||||||
slice_data = FuzzyAnchor.create_slice(text, s_line, e_line)
|
else: slice_data = {"start_line": s_line, "end_line": e_line}
|
||||||
else:
|
|
||||||
slice_data = {"start_line": s_line, "end_line": e_line}
|
|
||||||
slice_data['tag'] = 'auto-ast'
|
slice_data['tag'] = 'auto-ast'
|
||||||
slice_data['comment'] = name
|
slice_data['comment'] = name
|
||||||
f_item.custom_slices.append(slice_data)
|
f_item.custom_slices.append(slice_data)
|
||||||
@@ -1402,6 +1402,7 @@ class App:
|
|||||||
if not self._pending_patch_text:
|
if not self._pending_patch_text:
|
||||||
self._patch_error_message = "No patch to apply"
|
self._patch_error_message = "No patch to apply"
|
||||||
return
|
return
|
||||||
|
#TODO(Ed): Exception(Review)
|
||||||
try:
|
try:
|
||||||
base_dir = str(self.controller.current_project_dir) if hasattr(self.controller, 'current_project_dir') else "."
|
base_dir = str(self.controller.current_project_dir) if hasattr(self.controller, 'current_project_dir') else "."
|
||||||
success, msg = apply_patch_to_file(self._pending_patch_text, base_dir)
|
success, msg = apply_patch_to_file(self._pending_patch_text, base_dir)
|
||||||
@@ -1549,17 +1550,15 @@ if __name__ == "__main__":
|
|||||||
main()
|
main()
|
||||||
|
|
||||||
def render_main_interface(app: App) -> None:
|
def render_main_interface(app: App) -> None:
|
||||||
"""
|
"""Top-level per-frame orchestrator. Dispatches every subsystem in the correct order:
|
||||||
Top-level per-frame orchestrator. Dispatches every subsystem in the correct order:
|
|
||||||
error/stale overlay tints, perf bookends, GUI task draining, modal rendering,
|
error/stale overlay tints, perf bookends, GUI task draining, modal rendering,
|
||||||
auto-save, comms/tool-log caching, and all dockable windows.
|
auto-save, comms/tool-log caching, and all dockable windows.
|
||||||
|
|
||||||
SSDL Shape:
|
SSDL: `[I:overlays] -> [I:task_drain] -> [I:modals] -> [I:windows] -> [I:popups]`
|
||||||
`[I:overlays] -> [I:task_drain] -> [I:modals] -> [I:windows] -> [I:popups]`
|
|
||||||
|
|
||||||
ASCII Layout Map:
|
ASCII Layout Map:
|
||||||
Full-screen dockspace (managed by imgui_bundle):
|
Full-screen dockspace (managed by imgui_bundle):
|
||||||
+-------------------+------------------------------------+
|
+-------------------+-------------------------------------+
|
||||||
| Project Settings | Discussion Hub |
|
| Project Settings | Discussion Hub |
|
||||||
| AI Settings | +--------------------------------+ |
|
| AI Settings | +--------------------------------+ |
|
||||||
| Files & Media | | History entries (scrollable) | |
|
| Files & Media | | History entries (scrollable) | |
|
||||||
@@ -1567,7 +1566,7 @@ def render_main_interface(app: App) -> None:
|
|||||||
| MMA Dashboard | [splitter] |
|
| MMA Dashboard | [splitter] |
|
||||||
| Task DAG | [Message] [Response] |
|
| Task DAG | [Message] [Response] |
|
||||||
| Tier 1..4 streams | |
|
| Tier 1..4 streams | |
|
||||||
+-------------------+------------------+-----------------+
|
+-------------------+------------------+------------------+
|
||||||
| Operations Hub (tab-bar) | Theme window |
|
| Operations Hub (tab-bar) | Theme window |
|
||||||
| [Comms][Tools][Usage][Ext][Layouts] | |
|
| [Comms][Tools][Usage][Ext][Layouts] | |
|
||||||
+---------------------------------------+-----------------+
|
+---------------------------------------+-----------------+
|
||||||
@@ -1600,6 +1599,7 @@ def render_main_interface(app: App) -> None:
|
|||||||
render_tool_preset_manager_window(app)
|
render_tool_preset_manager_window(app)
|
||||||
render_persona_editor_window(app)
|
render_persona_editor_window(app)
|
||||||
|
|
||||||
|
#TODO(Ed): Exception(Review)
|
||||||
# Auto-save (every 60s)
|
# Auto-save (every 60s)
|
||||||
now = time.time()
|
now = time.time()
|
||||||
if now - app._last_autosave >= app._autosave_interval:
|
if now - app._last_autosave >= app._autosave_interval:
|
||||||
@@ -1666,10 +1666,8 @@ def render_main_interface(app: App) -> None:
|
|||||||
app._render_window_if_open("Context Preview", lambda: render_context_preview_window(app))
|
app._render_window_if_open("Context Preview", lambda: render_context_preview_window(app))
|
||||||
|
|
||||||
render_text_viewer_window(app)
|
render_text_viewer_window(app)
|
||||||
|
|
||||||
app.perf_monitor.end_frame()
|
app.perf_monitor.end_frame()
|
||||||
|
|
||||||
|
|
||||||
# Modals / Popups
|
# Modals / Popups
|
||||||
render_approve_script_modal(app)
|
render_approve_script_modal(app)
|
||||||
render_mma_modals(app)
|
render_mma_modals(app)
|
||||||
@@ -1683,12 +1681,10 @@ def render_custom_title_bar(app: App) -> None:
|
|||||||
#region: Diagnostics & Analytics
|
#region: Diagnostics & Analytics
|
||||||
|
|
||||||
def render_usage_analytics_panel(app: App) -> None:
|
def render_usage_analytics_panel(app: App) -> None:
|
||||||
"""
|
"""Renders the aggregate dashboard panel for usage, budgeting, cache analytics,
|
||||||
Renders the aggregate dashboard panel for usage, budgeting, cache analytics,
|
|
||||||
tool performance metrics, session insights, and RAG status.
|
tool performance metrics, session insights, and RAG status.
|
||||||
|
|
||||||
SSDL Shape:
|
SSDL:`[I:token_budget] -> [I:cache_panel] -> [I:tool_analytics] -> [I:session_insights] -> [I:rag_status]`
|
||||||
`[I:token_budget] -> [I:cache_panel] -> [I:tool_analytics] -> [I:session_insights] -> [I:rag_status]`
|
|
||||||
|
|
||||||
ASCII Layout Map:
|
ASCII Layout Map:
|
||||||
+---------------------------------------------------------+
|
+---------------------------------------------------------+
|
||||||
@@ -1728,13 +1724,11 @@ def render_usage_analytics_panel(app: App) -> None:
|
|||||||
if app.perf_profiling_enabled: app.perf_monitor.end_component("_render_usage_analytics_panel")
|
if app.perf_profiling_enabled: app.perf_monitor.end_component("_render_usage_analytics_panel")
|
||||||
|
|
||||||
def render_diagnostics_panel(app: App) -> None:
|
def render_diagnostics_panel(app: App) -> None:
|
||||||
"""
|
"""Renders the Diagnostics window. Shows FPS, frame time, CPU%, and input lag in a
|
||||||
Renders the Diagnostics window. Shows FPS, frame time, CPU%, and input lag in a
|
|
||||||
summary table; when profiling is on, shows per-component moving-average timings,
|
summary table; when profiling is on, shows per-component moving-average timings,
|
||||||
optional sparkline graphs, and the diagnostic message log.
|
optional sparkline graphs, and the diagnostic message log.
|
||||||
|
|
||||||
SSDL Shape:
|
SSDL: `[I:perf_summary_table] -> [B:enable_profiling] => [I:component_timings_table] -> [I:graphs] -> [I:diag_log]`
|
||||||
`[I:perf_summary_table] -> [B:enable_profiling] => [I:component_timings_table] -> [I:graphs] -> [I:diag_log]`
|
|
||||||
|
|
||||||
ASCII Layout Map:
|
ASCII Layout Map:
|
||||||
+---------------------------------------------------------+
|
+---------------------------------------------------------+
|
||||||
@@ -1777,16 +1771,11 @@ def render_diagnostics_panel(app: App) -> None:
|
|||||||
("CPU %", "cpu_percent", "%.1f"),
|
("CPU %", "cpu_percent", "%.1f"),
|
||||||
("Input Lag (ms)", "input_lag_ms", "%.1f")
|
("Input Lag (ms)", "input_lag_ms", "%.1f")
|
||||||
]:
|
]:
|
||||||
imgui.table_next_row()
|
imgui.table_next_row(); imgui.table_next_column()
|
||||||
imgui.table_next_column()
|
imgui.text(label); imgui.table_next_column()
|
||||||
imgui.text(label)
|
if key == "fps": avg_val = imgui.get_io().framerate
|
||||||
imgui.table_next_column()
|
else: avg_val = metrics.get(f"{key}_avg", metrics.get(key, 0.0))
|
||||||
if key == "fps":
|
imgui.text(format_str % avg_val); imgui.table_next_column()
|
||||||
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()
|
|
||||||
app.perf_show_graphs.setdefault(key, False)
|
app.perf_show_graphs.setdefault(key, False)
|
||||||
_, app.perf_show_graphs[key] = imgui.checkbox(f"##g_{key}", app.perf_show_graphs[key])
|
_, app.perf_show_graphs[key] = imgui.checkbox(f"##g_{key}", app.perf_show_graphs[key])
|
||||||
imgui.end_table()
|
imgui.end_table()
|
||||||
@@ -1809,21 +1798,14 @@ def render_diagnostics_panel(app: App) -> None:
|
|||||||
count = int(metrics.get(f"count_{comp_name}", 0))
|
count = int(metrics.get(f"count_{comp_name}", 0))
|
||||||
max_val = metrics.get(f"max_{comp_name}_ms", 0.0)
|
max_val = metrics.get(f"max_{comp_name}_ms", 0.0)
|
||||||
min_val = metrics.get(f"min_{comp_name}_ms", 0.0)
|
min_val = metrics.get(f"min_{comp_name}_ms", 0.0)
|
||||||
imgui.table_next_row()
|
imgui.table_next_row(); imgui.table_next_column()
|
||||||
imgui.table_next_column()
|
imgui.text(comp_name); imgui.table_next_column()
|
||||||
imgui.text(comp_name)
|
if avg_val > 10.0: imgui.text_colored(theme.get_color("status_error"), f"{avg_val:.2f}")
|
||||||
imgui.table_next_column()
|
else: imgui.text(f"{avg_val:.2f}")
|
||||||
if avg_val > 10.0:
|
|
||||||
imgui.text_colored(theme.get_color("status_error"), 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()
|
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()
|
||||||
app.perf_show_graphs.setdefault(comp_name, False)
|
app.perf_show_graphs.setdefault(comp_name, False)
|
||||||
_, app.perf_show_graphs[comp_name] = imgui.checkbox(f"##g_{comp_name}", app.perf_show_graphs[comp_name])
|
_, app.perf_show_graphs[comp_name] = imgui.checkbox(f"##g_{comp_name}", app.perf_show_graphs[comp_name])
|
||||||
imgui.end_table()
|
imgui.end_table()
|
||||||
@@ -1850,23 +1832,19 @@ def render_diagnostics_panel(app: App) -> None:
|
|||||||
for entry in reversed(app.controller.diagnostic_log):
|
for entry in reversed(app.controller.diagnostic_log):
|
||||||
imgui.table_next_row()
|
imgui.table_next_row()
|
||||||
imgui.table_next_column()
|
imgui.table_next_column()
|
||||||
imgui.text(entry.get("ts", ""))
|
imgui.text(entry.get("ts", "")); imgui.table_next_column()
|
||||||
imgui.table_next_column()
|
imgui.text(entry.get("type", "")); imgui.table_next_column()
|
||||||
imgui.text(entry.get("type", ""))
|
|
||||||
imgui.table_next_column()
|
|
||||||
imgui.text_wrapped(entry.get("message", ""))
|
imgui.text_wrapped(entry.get("message", ""))
|
||||||
imgui.end_table()
|
imgui.end_table()
|
||||||
|
|
||||||
if app.perf_profiling_enabled: app.perf_monitor.end_component("_render_diagnostics_panel")
|
if app.perf_profiling_enabled: app.perf_monitor.end_component("_render_diagnostics_panel")
|
||||||
|
|
||||||
def render_cache_panel(app: App) -> None:
|
def render_cache_panel(app: App) -> None:
|
||||||
"""
|
"""Renders Gemini cache analytics. Shows cache age, TTL remaining as a colour-coded
|
||||||
Renders Gemini cache analytics. Shows cache age, TTL remaining as a colour-coded
|
|
||||||
progress bar (green > 50%, yellow > 20%, red otherwise), and a [Clear Cache] button.
|
progress bar (green > 50%, yellow > 20%, red otherwise), and a [Clear Cache] button.
|
||||||
Skips rendering for non-Gemini providers.
|
Skips rendering for non-Gemini providers.
|
||||||
|
|
||||||
SSDL Shape:
|
SSDL: `[I:cache_stats] -> [B:progress_bar] => [B:clear_cache]`
|
||||||
`[I:cache_stats] -> [B:progress_bar] => [B:clear_cache]`
|
|
||||||
|
|
||||||
ASCII Layout Map:
|
ASCII Layout Map:
|
||||||
+---------------------------------------------------------+
|
+---------------------------------------------------------+
|
||||||
@@ -1909,12 +1887,10 @@ def render_cache_panel(app: App) -> None:
|
|||||||
if app.perf_profiling_enabled: app.perf_monitor.end_component("_render_cache_panel")
|
if app.perf_profiling_enabled: app.perf_monitor.end_component("_render_cache_panel")
|
||||||
|
|
||||||
def render_tool_analytics_panel(app: App) -> None:
|
def render_tool_analytics_panel(app: App) -> None:
|
||||||
"""
|
"""Renders a breakdown of tool execution telemetry: calls, average latency ms, and
|
||||||
Renders a breakdown of tool execution telemetry: calls, average latency ms, and
|
|
||||||
failure rate percentage per tool. Results are sorted by invocation count descending.
|
failure rate percentage per tool. Results are sorted by invocation count descending.
|
||||||
|
|
||||||
SSDL Shape:
|
SSDL: `[I:tool_stats] -> [B:stats_table]`
|
||||||
`[I:tool_stats] -> [B:stats_table]`
|
|
||||||
|
|
||||||
ASCII Layout Map:
|
ASCII Layout Map:
|
||||||
+---------------------------------------------------------+
|
+---------------------------------------------------------+
|
||||||
@@ -1952,12 +1928,9 @@ def render_tool_analytics_panel(app: App) -> None:
|
|||||||
avg_time = total_time / count if count > 0 else 0
|
avg_time = total_time / count if count > 0 else 0
|
||||||
fail_pct = (failures / count * 100) if count > 0 else 0
|
fail_pct = (failures / count * 100) if count > 0 else 0
|
||||||
imgui.table_next_row()
|
imgui.table_next_row()
|
||||||
imgui.table_set_column_index(0)
|
imgui.table_set_column_index(0); imgui.text(tool_name)
|
||||||
imgui.text(tool_name)
|
imgui.table_set_column_index(1); imgui.text(str(count))
|
||||||
imgui.table_set_column_index(1)
|
imgui.table_set_column_index(2); imgui.text(f"{avg_time:.0f}")
|
||||||
imgui.text(str(count))
|
|
||||||
imgui.table_set_column_index(2)
|
|
||||||
imgui.text(f"{avg_time:.0f}")
|
|
||||||
imgui.table_set_column_index(3)
|
imgui.table_set_column_index(3)
|
||||||
if fail_pct > 0: imgui.text_colored(theme.get_color("status_error"), f"{fail_pct:.0f}%")
|
if fail_pct > 0: imgui.text_colored(theme.get_color("status_error"), f"{fail_pct:.0f}%")
|
||||||
else: imgui.text("0%")
|
else: imgui.text("0%")
|
||||||
@@ -1965,13 +1938,11 @@ def render_tool_analytics_panel(app: App) -> None:
|
|||||||
if app.perf_profiling_enabled: app.perf_monitor.end_component("_render_tool_analytics_panel")
|
if app.perf_profiling_enabled: app.perf_monitor.end_component("_render_tool_analytics_panel")
|
||||||
|
|
||||||
def render_token_budget_panel(app: App) -> None:
|
def render_token_budget_panel(app: App) -> None:
|
||||||
"""
|
"""Renders prompt token utilization breakdown: session totals, cache read/creation stats,
|
||||||
Renders prompt token utilization breakdown: session totals, cache read/creation stats,
|
|
||||||
a colour-coded utilisation progress bar, component breakdown table (System/Tools/History),
|
a colour-coded utilisation progress bar, component breakdown table (System/Tools/History),
|
||||||
per-tier MMA cost table, trim warnings, and cache activity badge.
|
per-tier MMA cost table, trim warnings, and cache activity badge.
|
||||||
|
|
||||||
SSDL Shape:
|
SSDL: `[I:session_tokens] -> [B:utilization_bar] -> [B:breakdown_table] -> [B:tier_costs_table]`
|
||||||
`[I:session_tokens] -> [B:utilization_bar] -> [B:breakdown_table] -> [B:tier_costs_table]`
|
|
||||||
|
|
||||||
ASCII Layout Map:
|
ASCII Layout Map:
|
||||||
+---------------------------------------------------------+
|
+---------------------------------------------------------+
|
||||||
@@ -2107,12 +2078,10 @@ def render_token_budget_panel(app: App) -> None:
|
|||||||
#region: Logging
|
#region: Logging
|
||||||
|
|
||||||
def render_log_management(app: App) -> None:
|
def render_log_management(app: App) -> None:
|
||||||
"""
|
"""Renders the Log Management window. Enables browsing, starring (whitelisting), and loading
|
||||||
Renders the Log Management window. Enables browsing, starring (whitelisting), and loading
|
|
||||||
of prior log sessions from the log registry. Provides one-click prune and refresh actions.
|
of prior log sessions from the log registry. Provides one-click prune and refresh actions.
|
||||||
|
|
||||||
SSDL Shape:
|
SSDL: `[B:refresh | load | prune] -> [I:sessions_table] => [B:load | star/unstar per row]`
|
||||||
`[B:refresh | load | prune] -> [I:sessions_table] => [B:load | star/unstar per row]`
|
|
||||||
|
|
||||||
ASCII Layout Map:
|
ASCII Layout Map:
|
||||||
+---------------------------------------------------------+
|
+---------------------------------------------------------+
|
||||||
@@ -2159,30 +2128,21 @@ def render_log_management(app: App) -> None:
|
|||||||
for session_id, s_data in sessions.items():
|
for session_id, s_data in sessions.items():
|
||||||
imgui.table_next_row()
|
imgui.table_next_row()
|
||||||
imgui.table_next_column()
|
imgui.table_next_column()
|
||||||
imgui.text(session_id)
|
imgui.text(session_id); imgui.table_next_column()
|
||||||
imgui.table_next_column()
|
imgui.text(s_data.get("start_time", "")); imgui.table_next_column()
|
||||||
imgui.text(s_data.get("start_time", ""))
|
|
||||||
imgui.table_next_column()
|
|
||||||
whitelisted = s_data.get("whitelisted", False)
|
whitelisted = s_data.get("whitelisted", False)
|
||||||
if whitelisted:
|
if whitelisted: imgui.text_colored(theme.get_color("status_warning"), "YES")
|
||||||
imgui.text_colored(theme.get_color("status_warning"), "YES")
|
else: imgui.text("NO")
|
||||||
else:
|
imgui.table_next_column()
|
||||||
imgui.text("NO")
|
|
||||||
metadata = s_data.get("metadata") or {}
|
metadata = s_data.get("metadata") or {}
|
||||||
imgui.table_next_column()
|
imgui.text(metadata.get("reason", "")); imgui.table_next_column()
|
||||||
imgui.text(metadata.get("reason", ""))
|
imgui.text(str(metadata.get("size_kb", ""))); imgui.table_next_column()
|
||||||
imgui.table_next_column()
|
imgui.text(str(metadata.get("message_count", ""))); imgui.table_next_column()
|
||||||
imgui.text(str(metadata.get("size_kb", "")))
|
if imgui.button(f"Load##{session_id}"): app.cb_load_prior_log(s_data.get("path"))
|
||||||
imgui.table_next_column()
|
|
||||||
imgui.text(str(metadata.get("message_count", "")))
|
|
||||||
imgui.table_next_column()
|
|
||||||
if imgui.button(f"Load##{session_id}"):
|
|
||||||
app.cb_load_prior_log(s_data.get("path"))
|
|
||||||
imgui.same_line()
|
imgui.same_line()
|
||||||
if whitelisted:
|
if whitelisted:
|
||||||
if imgui.button(f"Unstar##{session_id}"):
|
if imgui.button(f"Unstar##{session_id}"):
|
||||||
registry.update_session_metadata(
|
registry.update_session_metadata(session_id,
|
||||||
session_id,
|
|
||||||
message_count = int(metadata.get("message_count") or 0),
|
message_count = int(metadata.get("message_count") or 0),
|
||||||
errors = int(metadata.get("errors") or 0),
|
errors = int(metadata.get("errors") or 0),
|
||||||
size_kb = int(metadata.get("size_kb") or 0),
|
size_kb = int(metadata.get("size_kb") or 0),
|
||||||
@@ -2191,8 +2151,7 @@ def render_log_management(app: App) -> None:
|
|||||||
)
|
)
|
||||||
else:
|
else:
|
||||||
if imgui.button(f"Star##{session_id}"):
|
if imgui.button(f"Star##{session_id}"):
|
||||||
registry.update_session_metadata(
|
registry.update_session_metadata(session_id,
|
||||||
session_id,
|
|
||||||
message_count = int(metadata.get("message_count") or 0),
|
message_count = int(metadata.get("message_count") or 0),
|
||||||
errors = int(metadata.get("errors") or 0),
|
errors = int(metadata.get("errors") or 0),
|
||||||
size_kb = int(metadata.get("size_kb") or 0),
|
size_kb = int(metadata.get("size_kb") or 0),
|
||||||
@@ -2208,11 +2167,9 @@ def render_log_management(app: App) -> None:
|
|||||||
#region: Project Management
|
#region: Project Management
|
||||||
|
|
||||||
def render_project_settings_hub(app: App) -> None:
|
def render_project_settings_hub(app: App) -> None:
|
||||||
"""
|
"""Renders the Project Settings Hub: a two-tab container for Projects and Paths configuration.
|
||||||
Renders the Project Settings Hub: a two-tab container for Projects and Paths configuration.
|
|
||||||
|
|
||||||
SSDL Shape:
|
SSDL: `[I:tab_bar] => [I:projects_panel] | [I:paths_panel]`
|
||||||
`[I:tab_bar] => [I:projects_panel] | [I:paths_panel]`
|
|
||||||
|
|
||||||
ASCII Layout Map:
|
ASCII Layout Map:
|
||||||
+---------------------------------------------------------+
|
+---------------------------------------------------------+
|
||||||
@@ -2229,13 +2186,11 @@ def render_project_settings_hub(app: App) -> None:
|
|||||||
if exp: render_paths_panel(app)
|
if exp: render_paths_panel(app)
|
||||||
|
|
||||||
def render_projects_panel(app: App) -> None:
|
def render_projects_panel(app: App) -> None:
|
||||||
"""
|
"""Renders the project configuration panel. Allows setting execution mode,
|
||||||
Renders the project configuration panel. Allows setting execution mode,
|
|
||||||
repository path, output/conductor directories, managing projects list,
|
repository path, output/conductor directories, managing projects list,
|
||||||
and global layout toggles (word-wrap, auto-scroll).
|
and global layout toggles (word-wrap, auto-scroll).
|
||||||
|
|
||||||
SSDL Shape:
|
SSDL: `[I:active_project] -> [B:execution_mode] -> [B:directories] -> [I:project_files] -> [B:project_actions] -> [B:toggles]`
|
||||||
`[I:active_project] -> [B:execution_mode] -> [B:directories] -> [I:project_files] -> [B:project_actions] -> [B:toggles]`
|
|
||||||
|
|
||||||
ASCII Layout Map:
|
ASCII Layout Map:
|
||||||
+---------------------------------------------------------+
|
+---------------------------------------------------------+
|
||||||
@@ -2313,8 +2268,7 @@ def render_projects_panel(app: App) -> None:
|
|||||||
filetypes = [("TOML", "*.toml"), ("All", "*.*")],
|
filetypes = [("TOML", "*.toml"), ("All", "*.*")],
|
||||||
)
|
)
|
||||||
r.destroy()
|
r.destroy()
|
||||||
if p and p not in app.project_paths:
|
if p and p not in app.project_paths: app.project_paths.append(p)
|
||||||
app.project_paths.append(p)
|
|
||||||
imgui.same_line()
|
imgui.same_line()
|
||||||
if imgui.button("New Project"):
|
if imgui.button("New Project"):
|
||||||
r = hide_tk_root()
|
r = hide_tk_root()
|
||||||
@@ -2338,12 +2292,10 @@ def render_projects_panel(app: App) -> None:
|
|||||||
if app.perf_profiling_enabled: app.perf_monitor.end_component("_render_projects_panel")
|
if app.perf_profiling_enabled: app.perf_monitor.end_component("_render_projects_panel")
|
||||||
|
|
||||||
def render_paths_panel(app: App) -> None:
|
def render_paths_panel(app: App) -> None:
|
||||||
"""
|
"""Renders the System Path Configuration panel. Shows source-tagged logs and scripts
|
||||||
Renders the System Path Configuration panel. Shows source-tagged logs and scripts
|
|
||||||
directory fields, each with a Browse button, and Apply / Reset buttons.
|
directory fields, each with a Browse button, and Apply / Reset buttons.
|
||||||
|
|
||||||
SSDL Shape:
|
SSDL: `[I:path_fields] => [B:apply_reset]`
|
||||||
`[I:path_fields] => [B:apply_reset]`
|
|
||||||
|
|
||||||
ASCII Layout Map:
|
ASCII Layout Map:
|
||||||
+---------------------------------------------------------+
|
+---------------------------------------------------------+
|
||||||
@@ -2399,7 +2351,7 @@ def render_ai_settings_hub(app: App) -> None:
|
|||||||
"""Groups and renders all AI-related configuration panels in a unified hub sidebar.
|
"""Groups and renders all AI-related configuration panels in a unified hub sidebar.
|
||||||
Includes persona selection, LLM provider settings, system prompts, RAG config, and tools.
|
Includes persona selection, LLM provider settings, system prompts, RAG config, and tools.
|
||||||
|
|
||||||
SSDL Shape: `[I:persona_selector] -> [B:provider_header] -> [B:system_prompts_header] -> [B:rag_header] -> [I:agent_tools]`
|
SSDL: `[I:persona_selector] -> [B:provider_header] -> [B:system_prompts_header] -> [B:rag_header] -> [I:agent_tools]`
|
||||||
|
|
||||||
ASCII Layout Map:
|
ASCII Layout Map:
|
||||||
+---------------------------------------------------------+
|
+---------------------------------------------------------+
|
||||||
@@ -2420,12 +2372,10 @@ def render_ai_settings_hub(app: App) -> None:
|
|||||||
render_agent_tools_panel(app)
|
render_agent_tools_panel(app)
|
||||||
|
|
||||||
def render_rag_panel(app: App) -> None:
|
def render_rag_panel(app: App) -> None:
|
||||||
"""
|
"""Renders RAG configuration panel. Exposes enable toggle, vector-store and embedding
|
||||||
Renders RAG configuration panel. Exposes enable toggle, vector-store and embedding
|
|
||||||
provider selectors, chunk size/overlap inputs, RAG status label, and a Rebuild Index button.
|
provider selectors, chunk size/overlap inputs, RAG status label, and a Rebuild Index button.
|
||||||
|
|
||||||
SSDL Shape:
|
SSDL: `[B:rag_switch] -> [B:combo_selectors] -> [B:chunking_inputs] => [B:rebuild_index]`
|
||||||
`[B:rag_switch] -> [B:combo_selectors] -> [B:chunking_inputs] => [B:rebuild_index]`
|
|
||||||
|
|
||||||
ASCII Layout Map:
|
ASCII Layout Map:
|
||||||
+---------------------------------------------------------+
|
+---------------------------------------------------------+
|
||||||
@@ -2444,23 +2394,23 @@ def render_rag_panel(app: App) -> None:
|
|||||||
|
|
||||||
imgui.text("Vector Store Provider")
|
imgui.text("Vector Store Provider")
|
||||||
providers = ['chroma', 'qdrant', 'mock']
|
providers = ['chroma', 'qdrant', 'mock']
|
||||||
|
#NOTE(Ed): Exception(Thirdparty)
|
||||||
try:
|
try:
|
||||||
idx = providers.index(conf.vector_store.provider)
|
idx = providers.index(conf.vector_store.provider)
|
||||||
except (ValueError, AttributeError):
|
except (ValueError, AttributeError):
|
||||||
idx = 0
|
idx = 0
|
||||||
ch2, next_idx = imgui.combo("##rag_provider", idx, providers)
|
ch2, next_idx = imgui.combo("##rag_provider", idx, providers)
|
||||||
if ch2:
|
if ch2: conf.vector_store.provider = providers[next_idx]
|
||||||
conf.vector_store.provider = providers[next_idx]
|
|
||||||
|
|
||||||
imgui.text("Embedding Provider")
|
imgui.text("Embedding Provider")
|
||||||
emb_providers = ['gemini', 'local']
|
emb_providers = ['gemini', 'local']
|
||||||
|
#NOTE(Ed): Exception(Thirdparty)
|
||||||
try:
|
try:
|
||||||
idx_e = emb_providers.index(conf.embedding_provider)
|
idx_e = emb_providers.index(conf.embedding_provider)
|
||||||
except (ValueError, AttributeError):
|
except (ValueError, AttributeError):
|
||||||
idx_e = 0
|
idx_e = 0
|
||||||
ch3, next_idx_e = imgui.combo("##rag_emb_provider", idx_e, emb_providers)
|
ch3, next_idx_e = imgui.combo("##rag_emb_provider", idx_e, emb_providers)
|
||||||
if ch3:
|
if ch3: conf.embedding_provider = emb_providers[next_idx_e]
|
||||||
conf.embedding_provider = emb_providers[next_idx_e]
|
|
||||||
|
|
||||||
imgui.text("Chunk Size")
|
imgui.text("Chunk Size")
|
||||||
imgui.set_next_item_width(150)
|
imgui.set_next_item_width(150)
|
||||||
@@ -2475,13 +2425,11 @@ def render_rag_panel(app: App) -> None:
|
|||||||
if imgui.button("Rebuild Index"): app.controller.event_queue.put('click', 'btn_rebuild_rag_index')
|
if imgui.button("Rebuild Index"): app.controller.event_queue.put('click', 'btn_rebuild_rag_index')
|
||||||
|
|
||||||
def render_system_prompts_panel(app: App) -> None:
|
def render_system_prompts_panel(app: App) -> None:
|
||||||
"""
|
"""Renders the System Prompts panel. Exposes global preset selector + multiline edit,
|
||||||
Renders the System Prompts panel. Exposes global preset selector + multiline edit,
|
|
||||||
base prompt toggle (default vs custom) with diff + reset, and project-level preset
|
base prompt toggle (default vs custom) with diff + reset, and project-level preset
|
||||||
selector + multiline edit.
|
selector + multiline edit.
|
||||||
|
|
||||||
SSDL Shape:
|
SSDL: `[B:global_preset_combo] -> [I:global_text] -> [B:base_prompt_header] -> [I:base_text] -> [B:project_preset_combo] -> [I:project_text]`
|
||||||
`[B:global_preset_combo] -> [I:global_text] -> [B:base_prompt_header] -> [I:base_text] -> [B:project_preset_combo] -> [I:project_text]`
|
|
||||||
|
|
||||||
ASCII Layout Map:
|
ASCII Layout Map:
|
||||||
+---------------------------------------------------------+
|
+---------------------------------------------------------+
|
||||||
@@ -2553,13 +2501,11 @@ def render_system_prompts_panel(app: App) -> None:
|
|||||||
ch, app.ui_project_system_prompt = imgui.input_text_multiline("##psp", app.ui_project_system_prompt, imgui.ImVec2(-1, 100))
|
ch, app.ui_project_system_prompt = imgui.input_text_multiline("##psp", app.ui_project_system_prompt, imgui.ImVec2(-1, 100))
|
||||||
|
|
||||||
def render_agent_tools_panel(app: App) -> None:
|
def render_agent_tools_panel(app: App) -> None:
|
||||||
"""
|
"""Renders the Active Tool Presets & Biases collapsible section. Shows a preset combo,
|
||||||
Renders the Active Tool Presets & Biases collapsible section. Shows a preset combo,
|
|
||||||
a Manage Presets button, and a Bias Profile combo. Displays a disabled notice when
|
a Manage Presets button, and a Bias Profile combo. Displays a disabled notice when
|
||||||
tool calling is unsupported by the active provider/model.
|
tool calling is unsupported by the active provider/model.
|
||||||
|
|
||||||
SSDL Shape:
|
SSDL: `[B:collapsing_header] => [B:preset_combo] -> [B:manage_presets] -> [B:bias_combo]`
|
||||||
`[B:collapsing_header] => [B:preset_combo] -> [B:manage_presets] -> [B:bias_combo]`
|
|
||||||
|
|
||||||
ASCII Layout Map:
|
ASCII Layout Map:
|
||||||
+---------------------------------------------------------+
|
+---------------------------------------------------------+
|
||||||
@@ -2580,14 +2526,14 @@ def render_agent_tools_panel(app: App) -> None:
|
|||||||
|
|
||||||
active = getattr(app, "ui_active_tool_preset", "")
|
active = getattr(app, "ui_active_tool_preset", "")
|
||||||
if active is None: active = ""
|
if active is None: active = ""
|
||||||
|
#NOTE(Ed): Exception(Thirdparty)
|
||||||
try:
|
try:
|
||||||
idx = preset_names.index(active)
|
idx = preset_names.index(active)
|
||||||
except ValueError:
|
except ValueError:
|
||||||
idx = 0
|
idx = 0
|
||||||
|
|
||||||
ch, new_idx = imgui.combo("##tool_preset_select", idx, preset_names)
|
ch, new_idx = imgui.combo("##tool_preset_select", idx, preset_names)
|
||||||
if ch:
|
if ch: app.ui_active_tool_preset = preset_names[new_idx]
|
||||||
app.ui_active_tool_preset = preset_names[new_idx]
|
|
||||||
|
|
||||||
imgui.same_line()
|
imgui.same_line()
|
||||||
if imgui.button("Manage Presets##tools"): app.show_tool_preset_manager_window = True
|
if imgui.button("Manage Presets##tools"): app.show_tool_preset_manager_window = True
|
||||||
@@ -2608,10 +2554,12 @@ def render_agent_tools_panel(app: App) -> None:
|
|||||||
|
|
||||||
imgui.dummy(imgui.ImVec2(0, 8))
|
imgui.dummy(imgui.ImVec2(0, 8))
|
||||||
cat_options = ["All"] + sorted(list(models.DEFAULT_TOOL_CATEGORIES.keys()))
|
cat_options = ["All"] + sorted(list(models.DEFAULT_TOOL_CATEGORIES.keys()))
|
||||||
|
#NOTE(Ed): Exception(Thirdparty)
|
||||||
try:
|
try:
|
||||||
f_idx = cat_options.index(app.ui_tool_filter_category)
|
f_idx = cat_options.index(app.ui_tool_filter_category)
|
||||||
except ValueError:
|
except ValueError:
|
||||||
f_idx = 0
|
f_idx = 0
|
||||||
|
|
||||||
imgui.set_next_item_width(200)
|
imgui.set_next_item_width(200)
|
||||||
ch_cat, next_f_idx = imgui.combo("Filter Category##agent", f_idx, cat_options)
|
ch_cat, next_f_idx = imgui.combo("Filter Category##agent", f_idx, cat_options)
|
||||||
if ch_cat: app.ui_tool_filter_category = cat_options[next_f_idx]
|
if ch_cat: app.ui_tool_filter_category = cat_options[next_f_idx]
|
||||||
@@ -2638,17 +2586,10 @@ def render_agent_tools_panel(app: App) -> None:
|
|||||||
imgui.tree_pop()
|
imgui.tree_pop()
|
||||||
|
|
||||||
def render_provider_panel(app: App) -> None:
|
def render_provider_panel(app: App) -> None:
|
||||||
"""
|
"""Renders the LLM provider configuration panel. Allows selection of API providers,
|
||||||
Renders the LLM provider configuration panel. Allows selection of API providers,
|
|
||||||
active models, hyper-parameters (temperature, max tokens, Top-P), history limits, and Gemini CLI binaries.
|
active models, hyper-parameters (temperature, max tokens, Top-P), history limits, and Gemini CLI binaries.
|
||||||
|
|
||||||
State Mutations:
|
SSDL: `[I:providers] -> [B:provider_combo] -> [B:model_listbox] -> [B:parameters_sliders] => [B:cli_path_browse]`
|
||||||
app.current_provider, app.current_model
|
|
||||||
app.temperature, app.max_tokens, app.top_p, app.history_trunc_limit
|
|
||||||
app.ui_gemini_cli_path
|
|
||||||
|
|
||||||
SSDL Shape:
|
|
||||||
`[I:providers] -> [B:provider_combo] -> [B:model_listbox] -> [B:parameters_sliders] => [B:cli_path_browse]`
|
|
||||||
"""
|
"""
|
||||||
if app.perf_profiling_enabled: app.perf_monitor.start_component("_render_provider_panel")
|
if app.perf_profiling_enabled: app.perf_monitor.start_component("_render_provider_panel")
|
||||||
imgui.text("Provider")
|
imgui.text("Provider")
|
||||||
@@ -2666,7 +2607,9 @@ def render_provider_panel(app: App) -> None:
|
|||||||
if app.current_provider == "llama":
|
if app.current_provider == "llama":
|
||||||
base_url = getattr(ai_client, "_llama_base_url", "")
|
base_url = getattr(ai_client, "_llama_base_url", "")
|
||||||
imgui.set_tooltip(f"Local backend: {base_url or 'unknown'}" if base_url else "Local backend")
|
imgui.set_tooltip(f"Local backend: {base_url or 'unknown'}" if base_url else "Local backend")
|
||||||
|
|
||||||
_render_v2_capability_badges(caps)
|
_render_v2_capability_badges(caps)
|
||||||
|
|
||||||
imgui.separator()
|
imgui.separator()
|
||||||
imgui.text("Model")
|
imgui.text("Model")
|
||||||
if imgui.begin_list_box("##models", imgui.ImVec2(-1, 120)):
|
if imgui.begin_list_box("##models", imgui.ImVec2(-1, 120)):
|
||||||
@@ -2728,21 +2671,10 @@ def render_provider_panel(app: App) -> None:
|
|||||||
if app.perf_profiling_enabled: app.perf_monitor.end_component("_render_provider_panel")
|
if app.perf_profiling_enabled: app.perf_monitor.end_component("_render_provider_panel")
|
||||||
|
|
||||||
def render_persona_selector_panel(app: App) -> None:
|
def render_persona_selector_panel(app: App) -> None:
|
||||||
"""
|
"""Renders the Persona Selection panel. Allows selecting profiles, editing persona definitions,
|
||||||
Renders the Persona Selection panel. Allows selecting profiles, editing persona definitions,
|
|
||||||
overriding system parameters (models, presets, prompts, bias profiles) and loading preset contexts.
|
overriding system parameters (models, presets, prompts, bias profiles) and loading preset contexts.
|
||||||
|
|
||||||
State Mutations:
|
SSDL: `[I:personas] -> [B:persona_combo] => [B:manage_personas]`
|
||||||
app.ui_active_persona, app._editing_persona_name, app._editing_persona_system_prompt,
|
|
||||||
app._editing_persona_tool_preset_id, app._editing_persona_bias_profile_id,
|
|
||||||
app._editing_persona_context_preset_id, app._editing_persona_aggregation_strategy,
|
|
||||||
app._editing_persona_preferred_models_list, app._editing_persona_is_new,
|
|
||||||
app.current_provider, app.current_model, app.temperature, app.max_tokens,
|
|
||||||
app.history_trunc_limit, app.ui_project_system_prompt, app.ui_active_tool_preset,
|
|
||||||
app.ui_active_bias_profile, app.ui_active_context_preset, app.show_persona_editor_window
|
|
||||||
|
|
||||||
SSDL Shape:
|
|
||||||
`[I:personas] -> [B:persona_combo] => [B:manage_personas]`
|
|
||||||
"""
|
"""
|
||||||
if app.perf_profiling_enabled: app.perf_monitor.start_component("_render_persona_selector_panel")
|
if app.perf_profiling_enabled: app.perf_monitor.start_component("_render_persona_selector_panel")
|
||||||
imgui.text("Persona")
|
imgui.text("Persona")
|
||||||
@@ -2768,10 +2700,8 @@ def render_persona_selector_panel(app: App) -> None:
|
|||||||
# Apply persona to current state immediately
|
# Apply persona to current state immediately
|
||||||
if persona.preferred_models and len(persona.preferred_models) > 0:
|
if persona.preferred_models and len(persona.preferred_models) > 0:
|
||||||
first_model = persona.preferred_models[0]
|
first_model = persona.preferred_models[0]
|
||||||
if first_model.get("provider"):
|
if first_model.get("provider"): app.current_provider = first_model.get("provider")
|
||||||
app.current_provider = first_model.get("provider")
|
if first_model.get("model"): app.current_model = first_model.get("model")
|
||||||
if first_model.get("model"):
|
|
||||||
app.current_model = first_model.get("model")
|
|
||||||
if first_model.get("temperature") is not None:
|
if first_model.get("temperature") is not None:
|
||||||
ai_client.temperature = first_model.get("temperature")
|
ai_client.temperature = first_model.get("temperature")
|
||||||
app.temperature = first_model.get("temperature")
|
app.temperature = first_model.get("temperature")
|
||||||
@@ -2790,6 +2720,7 @@ def render_persona_selector_panel(app: App) -> None:
|
|||||||
ai_client.set_bias_profile(persona.bias_profile)
|
ai_client.set_bias_profile(persona.bias_profile)
|
||||||
if getattr(persona, 'context_preset', None):
|
if getattr(persona, 'context_preset', None):
|
||||||
app.ui_active_context_preset = persona.context_preset
|
app.ui_active_context_preset = persona.context_preset
|
||||||
|
#TODO(Ed): Exception(Review)
|
||||||
try:
|
try:
|
||||||
app.load_context_preset(persona.context_preset)
|
app.load_context_preset(persona.context_preset)
|
||||||
except KeyError as e:
|
except KeyError as e:
|
||||||
@@ -2830,15 +2761,10 @@ def render_persona_selector_panel(app: App) -> None:
|
|||||||
if app.perf_profiling_enabled: app.perf_monitor.end_component("_render_persona_selector_panel")
|
if app.perf_profiling_enabled: app.perf_monitor.end_component("_render_persona_selector_panel")
|
||||||
|
|
||||||
def render_base_prompt_diff_modal(app: App) -> None:
|
def render_base_prompt_diff_modal(app: App) -> None:
|
||||||
"""
|
"""Renders a popup modal showing a unified diff between the default system prompt
|
||||||
Renders a popup modal showing a unified diff between the default system prompt
|
|
||||||
and the current custom base prompt.
|
and the current custom base prompt.
|
||||||
|
|
||||||
State Mutations:
|
SSDL: `[I:unified_diff] -> [I:diff_view_box] => [B:close]`
|
||||||
app.controller._show_base_prompt_diff_modal (closes/hides modal)
|
|
||||||
|
|
||||||
SSDL Shape:
|
|
||||||
`[I:unified_diff] -> [I:diff_view_box] => [B:close]`
|
|
||||||
"""
|
"""
|
||||||
if not getattr(app.controller, "_show_base_prompt_diff_modal", False):
|
if not getattr(app.controller, "_show_base_prompt_diff_modal", False):
|
||||||
return
|
return
|
||||||
@@ -2869,16 +2795,9 @@ def render_base_prompt_diff_modal(app: App) -> None:
|
|||||||
imgui.end_popup()
|
imgui.end_popup()
|
||||||
|
|
||||||
def render_save_preset_modal(app: App) -> None:
|
def render_save_preset_modal(app: App) -> None:
|
||||||
"""
|
"""Renders the popup modal for saving the current ImGui window layout preset.
|
||||||
Renders the popup modal for saving the current ImGui window layout preset.
|
|
||||||
|
|
||||||
State Mutations:
|
SSDL: `[I:preset_inputs] => [B:save_cancel]`
|
||||||
app._show_save_preset_modal (toggles visibility)
|
|
||||||
app._new_preset_name (stores input layout name)
|
|
||||||
app.layout_presets (saves layout definitions to configuration)
|
|
||||||
|
|
||||||
SSDL Shape:
|
|
||||||
`[I:preset_inputs] => [B:save_cancel]`
|
|
||||||
"""
|
"""
|
||||||
if not app._show_save_preset_modal: return
|
if not app._show_save_preset_modal: return
|
||||||
imgui.open_popup("Save Layout Preset")
|
imgui.open_popup("Save Layout Preset")
|
||||||
@@ -2904,16 +2823,10 @@ def render_save_preset_modal(app: App) -> None:
|
|||||||
imgui.close_current_popup()
|
imgui.close_current_popup()
|
||||||
|
|
||||||
def render_preset_manager_content(app: App, is_embedded: bool = False) -> None:
|
def render_preset_manager_content(app: App, is_embedded: bool = False) -> None:
|
||||||
"""
|
"""Renders the core prompt preset manager interface including the sidebar preset selector
|
||||||
Renders the core prompt preset manager interface including the sidebar preset selector
|
|
||||||
and the preset prompt content text editor.
|
and the preset prompt content text editor.
|
||||||
|
|
||||||
State Mutations:
|
SSDL: `[I:presets_list] -> [B:new_preset] -> [I:editor_meta] -> [I:editor_textbox] => [B:save_delete]`
|
||||||
app._selected_preset_idx
|
|
||||||
app._editing_preset_name, app._editing_preset_system_prompt, app._editing_preset_scope
|
|
||||||
|
|
||||||
SSDL Shape:
|
|
||||||
`[I:presets_list] -> [B:new_preset] -> [I:editor_meta] -> [I:editor_textbox] => [B:save_delete]`
|
|
||||||
"""
|
"""
|
||||||
avail = imgui.get_content_region_avail()
|
avail = imgui.get_content_region_avail()
|
||||||
if not hasattr(app, "_prompt_md_preview"): app._prompt_md_preview = False
|
if not hasattr(app, "_prompt_md_preview"): app._prompt_md_preview = False
|
||||||
@@ -3004,14 +2917,9 @@ def render_preset_manager_content(app: App, is_embedded: bool = False) -> None:
|
|||||||
imgui.end_table()
|
imgui.end_table()
|
||||||
|
|
||||||
def render_preset_manager_window(app: App, is_embedded: bool = False) -> None:
|
def render_preset_manager_window(app: App, is_embedded: bool = False) -> None:
|
||||||
"""
|
"""Renders the window container for the Prompt Presets Manager.
|
||||||
Renders the window container for the Prompt Presets Manager.
|
|
||||||
|
|
||||||
State Mutations:
|
SSDL: `[I] -> [I:window] => [I:preset_manager_content]`
|
||||||
app.show_preset_manager_window (visibility toggle)
|
|
||||||
|
|
||||||
SSDL Shape:
|
|
||||||
`[I] -> [I:window] => [I:preset_manager_content]`
|
|
||||||
"""
|
"""
|
||||||
if not app.show_preset_manager_window and not is_embedded: return
|
if not app.show_preset_manager_window and not is_embedded: return
|
||||||
if not is_embedded:
|
if not is_embedded:
|
||||||
@@ -3023,15 +2931,9 @@ def render_preset_manager_window(app: App, is_embedded: bool = False) -> None:
|
|||||||
render_preset_manager_content(app, is_embedded=is_embedded)
|
render_preset_manager_content(app, is_embedded=is_embedded)
|
||||||
|
|
||||||
def render_tool_preset_manager_content(app: App, is_embedded: bool = False) -> None:
|
def render_tool_preset_manager_content(app: App, is_embedded: bool = False) -> None:
|
||||||
"""
|
"""Renders the tool presets and tool capability profiles editor layout.
|
||||||
Renders the tool presets and tool capability profiles editor layout.
|
|
||||||
|
|
||||||
State Mutations:
|
SSDL: `[I:tool_presets] -> [B:new_tool_preset] -> [I:capability_toggles] -> [I:tools_list] => [B:save_delete]`
|
||||||
app._editing_tool_preset_name, app._editing_tool_preset_scope, app._selected_tool_preset_idx
|
|
||||||
app.controller (saves/deletes tool presets)
|
|
||||||
|
|
||||||
SSDL Shape:
|
|
||||||
`[I:tool_presets] -> [B:new_tool_preset] -> [I:capability_toggles] -> [I:tools_list] => [B:save_delete]`
|
|
||||||
"""
|
"""
|
||||||
avail = imgui.get_content_region_avail()
|
avail = imgui.get_content_region_avail()
|
||||||
if not hasattr(app, "_tool_split_v"): app._tool_split_v = 0.4
|
if not hasattr(app, "_tool_split_v"): app._tool_split_v = 0.4
|
||||||
@@ -3134,19 +3036,25 @@ def render_tool_preset_manager_content(app: App, is_embedded: bool = False) -> N
|
|||||||
imgui.begin_child("blist_pane", imgui.ImVec2(0, 0), False)
|
imgui.begin_child("blist_pane", imgui.ImVec2(0, 0), False)
|
||||||
if True:
|
if True:
|
||||||
if imgui.button("New Profile", imgui.ImVec2(-1, 0)):
|
if imgui.button("New Profile", imgui.ImVec2(-1, 0)):
|
||||||
app._editing_bias_profile_name = ""; app._editing_bias_profile_tool_weights = {}
|
app._editing_bias_profile_name = ""
|
||||||
app._editing_bias_profile_category_multipliers = {}; app._selected_bias_profile_idx = -1
|
app._editing_bias_profile_tool_weights = {}
|
||||||
|
app._editing_bias_profile_category_multipliers = {}
|
||||||
|
app._selected_bias_profile_idx = -1
|
||||||
imgui.separator(); bnames = sorted(app.bias_profiles.keys())
|
imgui.separator(); bnames = sorted(app.bias_profiles.keys())
|
||||||
for i, bname in enumerate(bnames):
|
for i, bname in enumerate(bnames):
|
||||||
if bname and imgui.selectable(f"{bname}##b_{i}", app._selected_bias_profile_idx == i)[0]:
|
if bname and imgui.selectable(f"{bname}##b_{i}", app._selected_bias_profile_idx == i)[0]:
|
||||||
app._selected_bias_profile_idx = i; app._editing_bias_profile_name = bname; prof = app.bias_profiles[bname]
|
app._selected_bias_profile_idx = i
|
||||||
app._editing_bias_profile_tool_weights = copy.deepcopy(prof.tool_weights); app._editing_bias_profile_category_multipliers = copy.deepcopy(prof.category_multipliers)
|
app._editing_bias_profile_name = bname;
|
||||||
|
prof = app.bias_profiles[bname]
|
||||||
|
app._editing_bias_profile_tool_weights = copy.deepcopy(prof.tool_weights)
|
||||||
|
app._editing_bias_profile_category_multipliers = copy.deepcopy(prof.category_multipliers)
|
||||||
imgui.end_child()
|
imgui.end_child()
|
||||||
|
|
||||||
imgui.table_next_column()
|
imgui.table_next_column()
|
||||||
imgui.begin_child("bedit_pane", imgui.ImVec2(0, 0), False)
|
imgui.begin_child("bedit_pane", imgui.ImVec2(0, 0), False)
|
||||||
if True:
|
if True:
|
||||||
imgui.text("Name:"); imgui.same_line(); imgui.set_next_item_width(-1); _, app._editing_bias_profile_name = imgui.input_text("##bname", app._editing_bias_profile_name)
|
imgui.text("Name:"); imgui.same_line(); imgui.set_next_item_width(-1)
|
||||||
|
_, app._editing_bias_profile_name = imgui.input_text("##bname", app._editing_bias_profile_name)
|
||||||
rem_bias_y = imgui.get_content_region_avail().y - 45
|
rem_bias_y = imgui.get_content_region_avail().y - 45
|
||||||
if app._bias_weights_open and app._bias_cats_open: bh1, bh2 = rem_bias_y * app._bias_split_v, rem_bias_y - (rem_bias_y * app._bias_split_v) - 10
|
if app._bias_weights_open and app._bias_cats_open: bh1, bh2 = rem_bias_y * app._bias_split_v, rem_bias_y - (rem_bias_y * app._bias_split_v) - 10
|
||||||
elif app._bias_weights_open: bh1, bh2 = rem_bias_y, 0
|
elif app._bias_weights_open: bh1, bh2 = rem_bias_y, 0
|
||||||
@@ -3161,9 +3069,11 @@ def render_tool_preset_manager_content(app: App, is_embedded: bool = False) -> N
|
|||||||
for cat_name, default_tools in models.DEFAULT_TOOL_CATEGORIES.items():
|
for cat_name, default_tools in models.DEFAULT_TOOL_CATEGORIES.items():
|
||||||
if imgui.tree_node(f"{cat_name}##b_list"):
|
if imgui.tree_node(f"{cat_name}##b_list"):
|
||||||
if imgui.begin_table(f"bt_{cat_name}", 2):
|
if imgui.begin_table(f"bt_{cat_name}", 2):
|
||||||
imgui.table_setup_column("T", imgui.TableColumnFlags_.width_fixed, 220); imgui.table_setup_column("W", imgui.TableColumnFlags_.width_stretch)
|
imgui.table_setup_column("T", imgui.TableColumnFlags_.width_fixed, 220)
|
||||||
|
imgui.table_setup_column("W", imgui.TableColumnFlags_.width_stretch)
|
||||||
for tn in default_tools:
|
for tn in default_tools:
|
||||||
imgui.table_next_row(); imgui.table_next_column(); imgui.text(tn); imgui.table_next_column()
|
imgui.table_next_row(); imgui.table_next_column()
|
||||||
|
imgui.text(tn); imgui.table_next_column()
|
||||||
curr_w = app._editing_bias_profile_tool_weights.get(tn, 3); imgui.set_next_item_width(-1)
|
curr_w = app._editing_bias_profile_tool_weights.get(tn, 3); imgui.set_next_item_width(-1)
|
||||||
ch_w, n_w = imgui.slider_int(f"##bw_{tn}", curr_w, 1, 10);
|
ch_w, n_w = imgui.slider_int(f"##bw_{tn}", curr_w, 1, 10);
|
||||||
if ch_w: app._editing_bias_profile_tool_weights[tn] = n_w
|
if ch_w: app._editing_bias_profile_tool_weights[tn] = n_w
|
||||||
@@ -3172,7 +3082,8 @@ def render_tool_preset_manager_content(app: App, is_embedded: bool = False) -> N
|
|||||||
imgui.end_child()
|
imgui.end_child()
|
||||||
if app._bias_cats_open:
|
if app._bias_cats_open:
|
||||||
imgui.button("###bias_splitter", imgui.ImVec2(-1, 4))
|
imgui.button("###bias_splitter", imgui.ImVec2(-1, 4))
|
||||||
if imgui.is_item_active(): app._bias_split_v = max(0.1, min(0.9, app._bias_split_v + imgui.get_io().mouse_delta.y / rem_bias_y))
|
if imgui.is_item_active():
|
||||||
|
app._bias_split_v = max(0.1, min(0.9, app._bias_split_v + imgui.get_io().mouse_delta.y / rem_bias_y))
|
||||||
|
|
||||||
opened_bc = imgui.collapsing_header("Category Multipliers", imgui.TreeNodeFlags_.default_open)
|
opened_bc = imgui.collapsing_header("Category Multipliers", imgui.TreeNodeFlags_.default_open)
|
||||||
if opened_bc != app._bias_cats_open: app._bias_cats_open = opened_bc
|
if opened_bc != app._bias_cats_open: app._bias_cats_open = opened_bc
|
||||||
@@ -3180,9 +3091,11 @@ def render_tool_preset_manager_content(app: App, is_embedded: bool = False) -> N
|
|||||||
imgui.begin_child("bcat_scroll", imgui.ImVec2(0, bh2), True)
|
imgui.begin_child("bcat_scroll", imgui.ImVec2(0, bh2), True)
|
||||||
if True:
|
if True:
|
||||||
if imgui.begin_table("bcats", 2):
|
if imgui.begin_table("bcats", 2):
|
||||||
imgui.table_setup_column("C", imgui.TableColumnFlags_.width_fixed, 220); imgui.table_setup_column("M", imgui.TableColumnFlags_.width_stretch)
|
imgui.table_setup_column("C", imgui.TableColumnFlags_.width_fixed, 220)
|
||||||
|
imgui.table_setup_column("M", imgui.TableColumnFlags_.width_stretch)
|
||||||
for cn in sorted(models.DEFAULT_TOOL_CATEGORIES.keys()):
|
for cn in sorted(models.DEFAULT_TOOL_CATEGORIES.keys()):
|
||||||
imgui.table_next_row(); imgui.table_next_column(); imgui.text(cn); imgui.table_next_column()
|
imgui.table_next_row(); imgui.table_next_column()
|
||||||
|
imgui.text(cn); imgui.table_next_column()
|
||||||
curr_m = app._editing_bias_profile_category_multipliers.get(cn, 1.0); imgui.set_next_item_width(-1)
|
curr_m = app._editing_bias_profile_category_multipliers.get(cn, 1.0); imgui.set_next_item_width(-1)
|
||||||
ch_m, n_m = imgui.slider_float(f"##cm_{cn}", curr_m, 0.1, 5.0, "%.1fx");
|
ch_m, n_m = imgui.slider_float(f"##cm_{cn}", curr_m, 0.1, 5.0, "%.1fx");
|
||||||
if ch_m: app._editing_bias_profile_category_multipliers[cn] = n_m
|
if ch_m: app._editing_bias_profile_category_multipliers[cn] = n_m
|
||||||
@@ -3202,24 +3115,25 @@ def render_tool_preset_manager_content(app: App, is_embedded: bool = False) -> N
|
|||||||
# --- Footer Buttons ---
|
# --- Footer Buttons ---
|
||||||
imgui.separator()
|
imgui.separator()
|
||||||
if imgui.button("Save##tp", imgui.ImVec2(100, 0)):
|
if imgui.button("Save##tp", imgui.ImVec2(100, 0)):
|
||||||
if app._editing_tool_preset_name.strip(): app.controller._cb_save_tool_preset(app._editing_tool_preset_name.strip(), app._editing_tool_preset_categories, app._editing_tool_preset_scope); app.ai_status = f"Saved: {app._editing_tool_preset_name}"
|
if app._editing_tool_preset_name.strip():
|
||||||
|
app.controller._cb_save_tool_preset(app._editing_tool_preset_name.strip(), app._editing_tool_preset_categories, app._editing_tool_preset_scope)
|
||||||
|
app.ai_status = f"Saved: {app._editing_tool_preset_name}"
|
||||||
imgui.same_line()
|
imgui.same_line()
|
||||||
if imgui.button("Delete##tp", imgui.ImVec2(100, 0)):
|
if imgui.button("Delete##tp", imgui.ImVec2(100, 0)):
|
||||||
if app._editing_tool_preset_name: app.controller._cb_delete_tool_preset(app._editing_tool_preset_name, app._editing_tool_preset_scope); app._editing_tool_preset_name = ""; app._selected_tool_preset_idx = -1
|
if app._editing_tool_preset_name:
|
||||||
|
app.controller._cb_delete_tool_preset(app._editing_tool_preset_name, app._editing_tool_preset_scope)
|
||||||
|
app._editing_tool_preset_name = ""
|
||||||
|
app._selected_tool_preset_idx = -1
|
||||||
imgui.same_line()
|
imgui.same_line()
|
||||||
if not is_embedded:
|
if not is_embedded:
|
||||||
if imgui.button("Close##tp", imgui.ImVec2(100, 0)): app.show_tool_preset_manager_window = False
|
if imgui.button("Close##tp", imgui.ImVec2(100, 0)):
|
||||||
|
app.show_tool_preset_manager_window = False
|
||||||
imgui.end_table()
|
imgui.end_table()
|
||||||
|
|
||||||
def render_tool_preset_manager_window(app: App, is_embedded: bool = False) -> None:
|
def render_tool_preset_manager_window(app: App, is_embedded: bool = False) -> None:
|
||||||
"""
|
"""Renders the window container for the Tool Preset Manager.
|
||||||
Renders the window container for the Tool Preset Manager.
|
|
||||||
|
|
||||||
State Mutations:
|
SSDL: `[I] -> [I:window] => [I:tool_preset_manager_content]`
|
||||||
app.show_tool_preset_manager_window (visibility toggle)
|
|
||||||
|
|
||||||
SSDL Shape:
|
|
||||||
`[I] -> [I:window] => [I:tool_preset_manager_content]`
|
|
||||||
"""
|
"""
|
||||||
if not app.show_tool_preset_manager_window and not is_embedded: return
|
if not app.show_tool_preset_manager_window and not is_embedded: return
|
||||||
if not is_embedded:
|
if not is_embedded:
|
||||||
@@ -3231,20 +3145,10 @@ def render_tool_preset_manager_window(app: App, is_embedded: bool = False) -> No
|
|||||||
render_tool_preset_manager_content(app, is_embedded=is_embedded)
|
render_tool_preset_manager_content(app, is_embedded=is_embedded)
|
||||||
|
|
||||||
def render_persona_editor_window(app: App, is_embedded: bool = False) -> None:
|
def render_persona_editor_window(app: App, is_embedded: bool = False) -> None:
|
||||||
"""
|
"""Renders the Persona Editor window, allowing creating, deleting, and modifying persona settings
|
||||||
Renders the Persona Editor window, allowing creating, deleting, and modifying persona settings
|
|
||||||
(prompts, preferred models list, tool presets, aggregation strategy, etc).
|
(prompts, preferred models list, tool presets, aggregation strategy, etc).
|
||||||
|
|
||||||
State Mutations:
|
SSDL: `[I:personas_list] -> [B:new_persona] -> [I:settings_editor] -> [I:models_list] -> [I:system_prompt_box] => [B:save_delete]`
|
||||||
app.show_persona_editor_window (visibility toggle)
|
|
||||||
app._editing_persona_name, app._editing_persona_system_prompt
|
|
||||||
app._editing_persona_tool_preset_id, app._editing_persona_bias_profile_id
|
|
||||||
app._editing_persona_context_preset_id, app._editing_persona_aggregation_strategy
|
|
||||||
app._editing_persona_preferred_models_list, app._editing_persona_is_new
|
|
||||||
app.controller (saves/deletes personas)
|
|
||||||
|
|
||||||
SSDL Shape:
|
|
||||||
`[I:personas_list] -> [B:new_persona] -> [I:settings_editor] -> [I:models_list] -> [I:system_prompt_box] => [B:save_delete]`
|
|
||||||
"""
|
"""
|
||||||
if not app.show_persona_editor_window and not is_embedded: return
|
if not app.show_persona_editor_window and not is_embedded: return
|
||||||
if not is_embedded:
|
if not is_embedded:
|
||||||
@@ -3273,11 +3177,12 @@ def render_persona_editor_window(app: App, is_embedded: bool = False) -> None:
|
|||||||
personas = getattr(app.controller, 'personas', {})
|
personas = getattr(app.controller, 'personas', {})
|
||||||
for name in sorted(personas.keys()):
|
for name in sorted(personas.keys()):
|
||||||
if name and imgui.selectable(f"{name}##p_list", name == app._editing_persona_name and not getattr(app, '_editing_persona_is_new', False))[0]:
|
if name and imgui.selectable(f"{name}##p_list", name == app._editing_persona_name and not getattr(app, '_editing_persona_is_new', False))[0]:
|
||||||
|
import copy; #TODO(Ed): Review local import
|
||||||
p = personas[name]; app._editing_persona_name = p.name; app._editing_persona_system_prompt = p.system_prompt or ""
|
p = personas[name]; app._editing_persona_name = p.name; app._editing_persona_system_prompt = p.system_prompt or ""
|
||||||
app._editing_persona_tool_preset_id = p.tool_preset or ""; app._editing_persona_bias_profile_id = p.bias_profile or ""
|
app._editing_persona_tool_preset_id = p.tool_preset or ""; app._editing_persona_bias_profile_id = p.bias_profile or ""
|
||||||
app._editing_persona_context_preset_id = getattr(p, 'context_preset', '') or ""
|
app._editing_persona_context_preset_id = getattr(p, 'context_preset', '') or ""
|
||||||
app._editing_persona_aggregation_strategy = getattr(p, 'aggregation_strategy', '') or ""
|
app._editing_persona_aggregation_strategy = getattr(p, 'aggregation_strategy', '') or ""
|
||||||
import copy; app._editing_persona_preferred_models_list = copy.deepcopy(p.preferred_models) if p.preferred_models else []
|
app._editing_persona_preferred_models_list = copy.deepcopy(p.preferred_models) if p.preferred_models else []
|
||||||
app._editing_persona_scope = app.controller.persona_manager.get_persona_scope(p.name); app._editing_persona_is_new = False
|
app._editing_persona_scope = app.controller.persona_manager.get_persona_scope(p.name); app._editing_persona_is_new = False
|
||||||
imgui.end_child()
|
imgui.end_child()
|
||||||
|
|
||||||
@@ -3287,7 +3192,8 @@ def render_persona_editor_window(app: App, is_embedded: bool = False) -> None:
|
|||||||
imgui.begin_child("persona_editor_content", imgui.ImVec2(0, avail.y - 45), False)
|
imgui.begin_child("persona_editor_content", imgui.ImVec2(0, avail.y - 45), False)
|
||||||
if True:
|
if True:
|
||||||
header_text = "New Persona" if getattr(app, '_editing_persona_is_new', True) else f"Editing Persona: {app._editing_persona_name}"
|
header_text = "New Persona" if getattr(app, '_editing_persona_is_new', True) else f"Editing Persona: {app._editing_persona_name}"
|
||||||
imgui.text_colored(C_IN(), header_text); imgui.separator()
|
imgui.text_colored(C_IN(), header_text)
|
||||||
|
imgui.separator()
|
||||||
|
|
||||||
if imgui.begin_table("p_meta", 2):
|
if imgui.begin_table("p_meta", 2):
|
||||||
imgui.table_setup_column("L", imgui.TableColumnFlags_.width_fixed, 60); imgui.table_setup_column("F", imgui.TableColumnFlags_.width_stretch)
|
imgui.table_setup_column("L", imgui.TableColumnFlags_.width_fixed, 60); imgui.table_setup_column("F", imgui.TableColumnFlags_.width_stretch)
|
||||||
@@ -3328,11 +3234,15 @@ def render_persona_editor_window(app: App, is_embedded: bool = False) -> None:
|
|||||||
with imscope.indent(20):
|
with imscope.indent(20):
|
||||||
if imgui.begin_table("model_settings", 2, imgui.TableFlags_.borders_inner_v):
|
if imgui.begin_table("model_settings", 2, imgui.TableFlags_.borders_inner_v):
|
||||||
imgui.table_setup_column("Label", imgui.TableColumnFlags_.width_fixed, 120); imgui.table_setup_column("Control", imgui.TableColumnFlags_.width_stretch)
|
imgui.table_setup_column("Label", imgui.TableColumnFlags_.width_fixed, 120); imgui.table_setup_column("Control", imgui.TableColumnFlags_.width_stretch)
|
||||||
imgui.table_next_row(); imgui.table_next_column(); imgui.text("Provider:"); imgui.table_next_column(); imgui.set_next_item_width(-1)
|
imgui.table_next_row(); imgui.table_next_column(); imgui.text("Provider:"); imgui.table_next_column();
|
||||||
p_idx = providers.index(prov) + 1 if prov in providers else 0; ch_p, p_idx = imgui.combo("##prov", p_idx, ["None"] + providers)
|
imgui.set_next_item_width(-1)
|
||||||
|
p_idx = providers.index(prov) + 1 if prov in providers else 0;
|
||||||
|
ch_p, p_idx = imgui.combo("##prov", p_idx, ["None"] + providers)
|
||||||
if ch_p: entry["provider"] = providers[p_idx-1] if p_idx > 0 else ""
|
if ch_p: entry["provider"] = providers[p_idx-1] if p_idx > 0 else ""
|
||||||
imgui.table_next_row(); imgui.table_next_column(); imgui.text("Model:"); imgui.table_next_column(); imgui.set_next_item_width(-1)
|
imgui.table_next_row(); imgui.table_next_column(); imgui.text("Model:"); imgui.table_next_column();
|
||||||
m_list = app.controller.all_available_models.get(entry.get("provider", ""), []); m_idx = m_list.index(mod) + 1 if mod in m_list else 0
|
imgui.set_next_item_width(-1)
|
||||||
|
m_list = app.controller.all_available_models.get(entry.get("provider", ""), [])
|
||||||
|
m_idx = m_list.index(mod) + 1 if mod in m_list else 0
|
||||||
ch_m, m_idx = imgui.combo("##model", m_idx, ["None"] + m_list)
|
ch_m, m_idx = imgui.combo("##model", m_idx, ["None"] + m_list)
|
||||||
if ch_m: entry["model"] = m_list[m_idx-1] if m_idx > 0 else ""
|
if ch_m: entry["model"] = m_list[m_idx-1] if m_idx > 0 else ""
|
||||||
imgui.table_next_row(); imgui.table_next_column(); imgui.text("Temperature:"); imgui.table_next_column(); cw = imgui.get_content_region_avail().x
|
imgui.table_next_row(); imgui.table_next_column(); imgui.text("Temperature:"); imgui.table_next_column(); cw = imgui.get_content_region_avail().x
|
||||||
@@ -3421,12 +3331,10 @@ def render_persona_editor_window(app: App, is_embedded: bool = False) -> None:
|
|||||||
#region: Context Management
|
#region: Context Management
|
||||||
|
|
||||||
def render_files_and_media(app: App) -> None:
|
def render_files_and_media(app: App) -> None:
|
||||||
"""
|
"""Renders the inventory of files and screenshots. Allows adding files or directories to the inventory
|
||||||
Renders the inventory of files and screenshots. Allows adding files or directories to the inventory
|
|
||||||
and attaching files or screenshots to the active context.
|
and attaching files or screenshots to the active context.
|
||||||
|
|
||||||
SSDL Shape:
|
SSDL: `[I:inventory] -> [B:add_files_folders] -> [I:screenshots] => [B:add_screenshots]`
|
||||||
`[I:inventory] -> [B:add_files_folders] -> [I:screenshots] => [B:add_screenshots]`
|
|
||||||
|
|
||||||
ASCII Layout Map:
|
ASCII Layout Map:
|
||||||
+---------------------------------------------------------+
|
+---------------------------------------------------------+
|
||||||
@@ -3482,12 +3390,9 @@ def render_files_and_media(app: App) -> None:
|
|||||||
if imgui.is_item_hovered(): imgui.set_tooltip(fpath)
|
if imgui.is_item_hovered(): imgui.set_tooltip(fpath)
|
||||||
|
|
||||||
imgui.table_set_column_index(2)
|
imgui.table_set_column_index(2)
|
||||||
if in_context:
|
if in_context: imgui.text_colored(theme.get_color("status_success"), "Active")
|
||||||
imgui.text_colored(theme.get_color("status_success"), "Active")
|
elif is_cached: imgui.text_colored(theme.get_color("status_info"), "Cached")
|
||||||
elif is_cached:
|
else: imgui.text_disabled(" - ")
|
||||||
imgui.text_colored(theme.get_color("status_info"), "Cached")
|
|
||||||
else:
|
|
||||||
imgui.text_disabled(" - ")
|
|
||||||
imgui.end_table()
|
imgui.end_table()
|
||||||
if to_remove_idx != -1: app.files.pop(to_remove_idx)
|
if to_remove_idx != -1: app.files.pop(to_remove_idx)
|
||||||
|
|
||||||
@@ -3530,12 +3435,10 @@ def render_files_and_media(app: App) -> None:
|
|||||||
return
|
return
|
||||||
|
|
||||||
def render_context_batch_actions(app: App, total_lines: int, total_ast: int) -> None:
|
def render_context_batch_actions(app: App, total_lines: int, total_ast: int) -> None:
|
||||||
"""
|
"""Renders a batch actions control bar. Allows batch-changing view modes of selected files,
|
||||||
Renders a batch actions control bar. Allows batch-changing view modes of selected files,
|
|
||||||
selecting/deselecting all, adding files, and generating context preview markdown.
|
selecting/deselecting all, adding files, and generating context preview markdown.
|
||||||
|
|
||||||
SSDL Shape:
|
SSDL: `[I:context_files] -> [B:mode_batch_buttons] -> [B:selection_buttons] -> [B:all_add_del] => [B:preview]`
|
||||||
`[I:context_files] -> [B:mode_batch_buttons] -> [B:selection_buttons] -> [B:all_add_del] => [B:preview]`
|
|
||||||
|
|
||||||
ASCII Layout Map:
|
ASCII Layout Map:
|
||||||
+---------------------------------------------------------+
|
+---------------------------------------------------------+
|
||||||
@@ -3593,12 +3496,10 @@ def render_context_batch_actions(app: App, total_lines: int, total_ast: int) ->
|
|||||||
imgui.text(f" | Total: {len(app.context_files)} files, {total_lines} lines, {total_ast} AST elements")
|
imgui.text(f" | Total: {len(app.context_files)} files, {total_lines} lines, {total_ast} AST elements")
|
||||||
|
|
||||||
def render_add_context_files_modal(app: App) -> None:
|
def render_add_context_files_modal(app: App) -> None:
|
||||||
"""
|
"""Renders a modal popup listing files in the project inventory that can be batch-added
|
||||||
Renders a modal popup listing files in the project inventory that can be batch-added
|
|
||||||
to the active context.
|
to the active context.
|
||||||
|
|
||||||
SSDL Shape:
|
SSDL: `[I:picker_list] -> [B:checkboxes] -> [B:add_selected_button] => [B:cancel_button]`
|
||||||
`[I:picker_list] -> [B:checkboxes] -> [B:add_selected_button] => [B:cancel_button]`
|
|
||||||
|
|
||||||
ASCII Layout Map:
|
ASCII Layout Map:
|
||||||
+---------------------------------------------------------+
|
+---------------------------------------------------------+
|
||||||
@@ -3649,12 +3550,10 @@ def render_add_context_files_modal(app: App) -> None:
|
|||||||
imgui.end_popup()
|
imgui.end_popup()
|
||||||
|
|
||||||
def render_context_composition_panel(app: App) -> None:
|
def render_context_composition_panel(app: App) -> None:
|
||||||
"""
|
"""Renders the Context Composition panel containing loaded project files, presets,
|
||||||
Renders the Context Composition panel containing loaded project files, presets,
|
|
||||||
and visual screenshot files. Displays token stats, batch files actions, and collapsible trees.
|
and visual screenshot files. Displays token stats, batch files actions, and collapsible trees.
|
||||||
|
|
||||||
SSDL Shape:
|
SSDL: `[I:stats] -> [I:batch_actions] -> [I:files_table] -> [I:presets] -> [I:screenshots]`
|
||||||
`[I:stats] -> [I:batch_actions] -> [I:files_table] -> [I:presets] -> [I:screenshots]`
|
|
||||||
|
|
||||||
ASCII Layout Map:
|
ASCII Layout Map:
|
||||||
+-------------------------------------------------------------+
|
+-------------------------------------------------------------+
|
||||||
@@ -7275,13 +7174,11 @@ def render_task_dag_panel(app: App) -> None: # 4. Task DAG Visualizer
|
|||||||
imgui.text_disabled("No active MMA track or tickets.")
|
imgui.text_disabled("No active MMA track or tickets.")
|
||||||
|
|
||||||
def render_beads_tab(app: App) -> None:
|
def render_beads_tab(app: App) -> None:
|
||||||
"""
|
"""Renders the Beads Graph tab. Checks for `dolt` and `bd` CLI availability,
|
||||||
Renders the Beads Graph tab. Checks for `dolt` and `bd` CLI availability,
|
|
||||||
shows a warning if missing, then lists beads from the Dolt-backed BeadsClient
|
shows a warning if missing, then lists beads from the Dolt-backed BeadsClient
|
||||||
in a 3-column table (ID / Status / Title).
|
in a 3-column table (ID / Status / Title).
|
||||||
|
|
||||||
SSDL Shape:
|
SSDL Shape: `[I:dep_check] -> [B:refresh] -> [I:beads_table]`
|
||||||
`[I:dep_check] -> [B:refresh] -> [I:beads_table]`
|
|
||||||
|
|
||||||
ASCII Layout Map:
|
ASCII Layout Map:
|
||||||
+---------------------------------------------------------+
|
+---------------------------------------------------------+
|
||||||
@@ -7324,24 +7221,18 @@ def render_beads_tab(app: App) -> None:
|
|||||||
imgui.table_setup_column("Title")
|
imgui.table_setup_column("Title")
|
||||||
imgui.table_headers_row()
|
imgui.table_headers_row()
|
||||||
for b in beads:
|
for b in beads:
|
||||||
imgui.table_next_row()
|
imgui.table_next_row(); imgui.table_next_column()
|
||||||
imgui.table_next_column()
|
imgui.text(str(b.id)); imgui.table_next_column()
|
||||||
imgui.text(str(b.id))
|
imgui.text(str(b.status)); imgui.table_next_column(); imgui.text(str(b.title))
|
||||||
imgui.table_next_column()
|
|
||||||
imgui.text(str(b.status))
|
|
||||||
imgui.table_next_column()
|
|
||||||
imgui.text(str(b.title))
|
|
||||||
imgui.end_table()
|
imgui.end_table()
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
imgui.text_colored(theme.get_color("status_error"), f"Error loading beads: {e}")
|
imgui.text_colored(theme.get_color("status_error"), f"Error loading beads: {e}")
|
||||||
|
|
||||||
def render_mma_focus_selector(app: App) -> None:
|
def render_mma_focus_selector(app: App) -> None:
|
||||||
"""
|
"""Renders the Focus Agent selector. Filters the discussion entries list to show
|
||||||
Renders the Focus Agent selector. Filters the discussion entries list to show
|
|
||||||
only the output of the chosen tier agent (or All). Includes a clear [x] button.
|
only the output of the chosen tier agent (or All). Includes a clear [x] button.
|
||||||
|
|
||||||
SSDL Shape:
|
SSDL: `[I:focus_combo] -> [B:clear_x?]`
|
||||||
`[I:focus_combo] -> [B:clear_x?]`
|
|
||||||
|
|
||||||
ASCII Layout Map:
|
ASCII Layout Map:
|
||||||
+---------------------------------------------------------+
|
+---------------------------------------------------------+
|
||||||
|
|||||||
Reference in New Issue
Block a user