fixing regresssions
This commit is contained in:
@@ -134,7 +134,9 @@ def _get_combined_system_prompt() -> str:
|
||||
return f"{_SYSTEM_PROMPT}\n\n[USER SYSTEM PROMPT]\n{_custom_system_prompt}"
|
||||
return _SYSTEM_PROMPT
|
||||
|
||||
_comms_log: list[dict[str, Any]] = []
|
||||
from collections import deque
|
||||
|
||||
_comms_log: deque[dict[str, Any]] = deque(maxlen=1000)
|
||||
|
||||
COMMS_CLAMP_CHARS: int = 300
|
||||
|
||||
@@ -147,6 +149,7 @@ def _append_comms(direction: str, kind: str, payload: dict[str, Any]) -> None:
|
||||
"model": _model,
|
||||
"payload": payload,
|
||||
"source_tier": get_current_tier(),
|
||||
"local_ts": time.time(),
|
||||
}
|
||||
_comms_log.append(entry)
|
||||
if comms_log_callback is not None:
|
||||
|
||||
@@ -822,13 +822,6 @@ class AppController:
|
||||
sys.stderr.write("[DEBUG] _process_event_queue entered\n")
|
||||
sys.stderr.flush()
|
||||
|
||||
def tick_perf():
|
||||
while True:
|
||||
self.perf_monitor.start_frame()
|
||||
time.sleep(0.01) # Measurable frame time
|
||||
self.perf_monitor.end_frame()
|
||||
time.sleep(0.006) # Aim for ~60 FPS total
|
||||
threading.Thread(target=tick_perf, daemon=True).start()
|
||||
while True:
|
||||
event_name, payload = self.event_queue.get()
|
||||
sys.stderr.write(f"[DEBUG] _process_event_queue got event: {event_name} with payload: {str(payload)[:100]}\n")
|
||||
|
||||
252
src/gui_2.py
252
src/gui_2.py
@@ -109,6 +109,8 @@ class App:
|
||||
self.ui_separate_response_panel = gui_cfg.get("separate_response_panel", False)
|
||||
self._comms_log_cache: list[dict[str, Any]] = []
|
||||
self._comms_log_dirty: bool = True
|
||||
self._tool_log_cache: list[dict[str, Any]] = []
|
||||
self._tool_log_dirty: bool = True
|
||||
self._last_ui_focus_agent: Optional[str] = None
|
||||
|
||||
def _handle_approve_tool(self, user_data=None) -> None:
|
||||
@@ -184,22 +186,23 @@ class App:
|
||||
self.show_text_viewer = True
|
||||
self.text_viewer_title = label
|
||||
self.text_viewer_content = content
|
||||
|
||||
if not content:
|
||||
imgui.text_disabled("(empty)")
|
||||
return
|
||||
|
||||
if len(content) > COMMS_CLAMP_CHARS:
|
||||
if self.ui_word_wrap:
|
||||
imgui.push_text_wrap_pos(imgui.get_content_region_avail().x)
|
||||
imgui.text(content)
|
||||
imgui.pop_text_wrap_pos()
|
||||
else:
|
||||
imgui.begin_child(f"heavy_text_child_{label}", imgui.ImVec2(0, 80), True)
|
||||
imgui.input_text_multiline(f"##{label}_input", content, imgui.ImVec2(-1, -1), imgui.InputTextFlags_.read_only)
|
||||
imgui.end_child()
|
||||
# Use a fixed-height multi-line input box for large text to avoid expensive frame-by-frame wrapping
|
||||
imgui.begin_child(f"heavy_text_child_{label}_{hash(content)}", imgui.ImVec2(0, 80), True)
|
||||
imgui.input_text_multiline(f"##{label}_input", content, imgui.ImVec2(-1, -1), imgui.InputTextFlags_.read_only)
|
||||
imgui.end_child()
|
||||
else:
|
||||
if self.ui_word_wrap:
|
||||
imgui.push_text_wrap_pos(imgui.get_content_region_avail().x)
|
||||
imgui.text(content if content else "(empty)")
|
||||
imgui.push_text_wrap_pos(0.0)
|
||||
imgui.text_unformatted(content)
|
||||
imgui.pop_text_wrap_pos()
|
||||
else:
|
||||
imgui.text(content if content else "(empty)")
|
||||
imgui.text_unformatted(content)
|
||||
# ---------------------------------------------------------------- gui
|
||||
|
||||
def _show_menus(self) -> None:
|
||||
@@ -272,6 +275,7 @@ class App:
|
||||
|
||||
if self.ui_focus_agent != self._last_ui_focus_agent:
|
||||
self._comms_log_dirty = True
|
||||
self._tool_log_dirty = True
|
||||
self._last_ui_focus_agent = self.ui_focus_agent
|
||||
|
||||
if self._comms_log_dirty:
|
||||
@@ -284,12 +288,23 @@ class App:
|
||||
else:
|
||||
self._comms_log_cache = log_raw
|
||||
self._comms_log_dirty = False
|
||||
|
||||
if self._tool_log_dirty:
|
||||
log_raw = list(self._tool_log)
|
||||
if self.ui_focus_agent:
|
||||
self._tool_log_cache = [e for e in log_raw if e.get("source_tier") == self.ui_focus_agent]
|
||||
else:
|
||||
self._tool_log_cache = log_raw
|
||||
self._tool_log_dirty = False
|
||||
|
||||
with self._pending_tool_calls_lock:
|
||||
if self._pending_tool_calls and self.ui_auto_scroll_tool_calls:
|
||||
self._scroll_tool_calls_to_bottom = True
|
||||
for tc in self._pending_tool_calls:
|
||||
self._tool_log.append(tc)
|
||||
self._pending_tool_calls.clear()
|
||||
if self._pending_tool_calls:
|
||||
if self.ui_auto_scroll_tool_calls:
|
||||
self._scroll_tool_calls_to_bottom = True
|
||||
self._tool_log_dirty = True
|
||||
for tc in self._pending_tool_calls:
|
||||
self._tool_log.append(tc)
|
||||
self._pending_tool_calls.clear()
|
||||
if self.show_windows.get("Context Hub", False):
|
||||
exp, opened = imgui.begin("Context Hub", self.show_windows["Context Hub"])
|
||||
self.show_windows["Context Hub"] = bool(opened)
|
||||
@@ -1359,18 +1374,15 @@ class App:
|
||||
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 ---
|
||||
if self.ui_word_wrap:
|
||||
imgui.begin_child("resp_wrap", imgui.ImVec2(-1, -40), True)
|
||||
imgui.push_text_wrap_pos(imgui.get_content_region_avail().x)
|
||||
imgui.text(self.ai_response)
|
||||
imgui.pop_text_wrap_pos()
|
||||
imgui.end_child()
|
||||
else:
|
||||
imgui.input_text_multiline("##ai_out", self.ai_response, imgui.ImVec2(-1, -40), imgui.InputTextFlags_.read_only)
|
||||
|
||||
imgui.begin_child("response_scroll_area", imgui.ImVec2(0, -40), True)
|
||||
imgui.input_text_multiline("##ai_out", self.ai_response, imgui.ImVec2(-1, -1), imgui.InputTextFlags_.read_only)
|
||||
imgui.end_child()
|
||||
|
||||
imgui.separator()
|
||||
if imgui.button("-> History"):
|
||||
if self.ai_response:
|
||||
self.disc_entries.append({"role": "AI", "content": self.ai_response, "collapsed": False, "ts": project_manager.now_ts()})
|
||||
self.disc_entries.append({"role": "AI", "content": self.ai_response, "collapsed": True, "ts": project_manager.now_ts()})
|
||||
if is_blinking:
|
||||
imgui.pop_style_color(2)
|
||||
|
||||
@@ -1380,6 +1392,7 @@ class App:
|
||||
if imgui.button("Clear##comms"):
|
||||
ai_client.clear_comms_log()
|
||||
self._comms_log.clear()
|
||||
self._comms_log_dirty = True
|
||||
imgui.same_line()
|
||||
if imgui.button("Load Log"):
|
||||
self.cb_load_prior_log()
|
||||
@@ -1391,40 +1404,48 @@ class App:
|
||||
self._comms_log_dirty = True
|
||||
self.ai_status = "idle"
|
||||
imgui.separator()
|
||||
imgui.text_colored(vec4(255, 200, 100), "VIEWING PRIOR SESSION")
|
||||
imgui.separator()
|
||||
imgui.text_colored(C_OUT, "OUT")
|
||||
imgui.same_line()
|
||||
imgui.text_colored(C_REQ, "request")
|
||||
imgui.same_line()
|
||||
imgui.text_colored(C_TC, "tool_call")
|
||||
imgui.same_line()
|
||||
imgui.text(" ")
|
||||
imgui.same_line()
|
||||
imgui.text_colored(C_IN, "IN")
|
||||
imgui.same_line()
|
||||
imgui.text_colored(C_RES, "response")
|
||||
imgui.same_line()
|
||||
imgui.text_colored(C_TR, "tool_result")
|
||||
imgui.separator()
|
||||
|
||||
# Use tinted background for prior session
|
||||
if self.is_viewing_prior_session:
|
||||
imgui.push_style_color(imgui.Col_.child_bg, vec4(40, 30, 20))
|
||||
|
||||
imgui.begin_child("comms_scroll", imgui.ImVec2(0, 0), False, imgui.WindowFlags_.horizontal_scrollbar)
|
||||
|
||||
log_to_render = self._comms_log_cache
|
||||
|
||||
flags = imgui.TableFlags_.resizable | imgui.TableFlags_.hideable | imgui.TableFlags_.borders_inner_v | imgui.TableFlags_.row_bg | imgui.TableFlags_.scroll_y
|
||||
|
||||
if imgui.begin_table("comms_table", 5, flags):
|
||||
# Set a max height for the table or use available region
|
||||
avail = imgui.get_content_region_avail()
|
||||
if imgui.begin_table("comms_table", 6, flags, imgui.ImVec2(0, avail.y)):
|
||||
imgui.table_setup_column("#", imgui.TableColumnFlags_.width_fixed, 40)
|
||||
imgui.table_setup_column("Tier", imgui.TableColumnFlags_.width_fixed, 60)
|
||||
imgui.table_setup_column("Type", imgui.TableColumnFlags_.width_fixed, 80)
|
||||
imgui.table_setup_column("!", imgui.TableColumnFlags_.width_fixed, 20)
|
||||
imgui.table_setup_column("Content", imgui.TableColumnFlags_.width_stretch)
|
||||
imgui.table_setup_column("Action", imgui.TableColumnFlags_.width_fixed, 50)
|
||||
|
||||
imgui.table_headers_row()
|
||||
|
||||
def payload_to_str(msg_kind, payload):
|
||||
if msg_kind == "request":
|
||||
return payload.get("message", "")
|
||||
elif msg_kind == "response":
|
||||
r = payload.get("round", 0)
|
||||
sr = payload.get("stop_reason", "STOP")
|
||||
text = payload.get("text", "")
|
||||
tcs = payload.get("tool_calls", [])
|
||||
tc_str = f" ({len(tcs)} tool calls)" if tcs else ""
|
||||
return f"[R{r}] [{sr}]{tc_str} {text}"
|
||||
elif msg_kind == "tool_call":
|
||||
content = f"Call: {payload.get('name', '?')}"
|
||||
if "script" in payload:
|
||||
content += f" | Script: {payload['script']}"
|
||||
elif "args" in payload:
|
||||
content += f" | Args: {json.dumps(payload['args'])}"
|
||||
return content
|
||||
elif msg_kind == "tool_result":
|
||||
return f"Result: {payload.get('name', '?')} | {payload.get('output', '')}"
|
||||
return str(payload)
|
||||
|
||||
clipper = imgui.ListClipper()
|
||||
clipper.begin(len(log_to_render))
|
||||
while clipper.step():
|
||||
@@ -1434,18 +1455,23 @@ class App:
|
||||
|
||||
i_display = i + 1
|
||||
source = entry.get("source_tier", "main")
|
||||
msg_type = entry.get("type", "?")
|
||||
content_text = entry.get("content", "")
|
||||
if len(content_text) > COMMS_CLAMP_CHARS:
|
||||
content_text = content_text[:COMMS_CLAMP_CHARS] + "..."
|
||||
msg_kind = entry.get("kind", entry.get("type", "?")) # Handle legacy 'type'
|
||||
payload = entry.get("payload", {})
|
||||
if not payload and msg_kind not in ("request", "response", "tool_call", "tool_result"):
|
||||
payload = entry # Legacy format where entry IS the payload
|
||||
|
||||
# FG Color based on type
|
||||
full_content = payload_to_str(msg_kind, payload)
|
||||
content_preview = full_content
|
||||
if len(content_preview) > 500: # Increased clamp
|
||||
content_preview = content_preview[:500] + "..."
|
||||
|
||||
# FG Color based on kind
|
||||
fg = C_VAL
|
||||
if msg_type == "request": fg = C_REQ
|
||||
elif msg_type == "response": fg = C_RES
|
||||
elif msg_type == "tool_call": fg = C_TC
|
||||
elif msg_type == "tool_result": fg = C_TR
|
||||
elif msg_type == "error": fg = vec4(255, 80, 80)
|
||||
if msg_kind == "request": fg = C_REQ
|
||||
elif msg_kind == "response": fg = C_RES
|
||||
elif msg_kind == "tool_call": fg = C_TC
|
||||
elif msg_kind == "tool_result": fg = C_TR
|
||||
elif msg_kind == "error": fg = vec4(255, 80, 80)
|
||||
|
||||
imgui.table_next_column()
|
||||
imgui.text_colored(C_LBL, f"#{i_display}")
|
||||
@@ -1454,7 +1480,7 @@ class App:
|
||||
imgui.text_colored(C_SUB, f"[{source}]")
|
||||
|
||||
imgui.table_next_column()
|
||||
imgui.text_colored(fg, msg_type)
|
||||
imgui.text_colored(fg, msg_kind)
|
||||
|
||||
imgui.table_next_column()
|
||||
elapsed = time.time() - entry.get("local_ts", 0)
|
||||
@@ -1467,18 +1493,25 @@ class App:
|
||||
imgui.table_next_column()
|
||||
if self.ui_word_wrap:
|
||||
imgui.push_text_wrap_pos(0.0)
|
||||
imgui.text_unformatted(content_text)
|
||||
imgui.text_unformatted(content_preview)
|
||||
imgui.pop_text_wrap_pos()
|
||||
else:
|
||||
imgui.text_unformatted(content_text)
|
||||
imgui.text_unformatted(content_preview)
|
||||
|
||||
imgui.table_next_column()
|
||||
if imgui.button(f"View##{i}"):
|
||||
self.text_viewer_title = f"Log Entry #{i_display} ({msg_kind})"
|
||||
self.text_viewer_content = full_content
|
||||
self.show_text_viewer = True
|
||||
|
||||
imgui.end_table()
|
||||
|
||||
if self._scroll_comms_to_bottom:
|
||||
imgui.set_scroll_here_y(1.0)
|
||||
self._scroll_comms_to_bottom = False
|
||||
# Table with scroll_y handles its own scrolling
|
||||
# We might need ed.set_scroll_y or similar if we wanted precise control
|
||||
# but usually imgui.set_scroll_here_y works inside the table
|
||||
pass
|
||||
|
||||
imgui.end_child()
|
||||
if self.is_viewing_prior_session:
|
||||
imgui.pop_style_color()
|
||||
|
||||
@@ -1487,57 +1520,56 @@ class App:
|
||||
imgui.same_line()
|
||||
if imgui.button("Clear##tc"):
|
||||
self._tool_log.clear()
|
||||
self._tool_log_dirty = True
|
||||
imgui.separator()
|
||||
imgui.begin_child("scroll_area")
|
||||
clipper = imgui.ListClipper()
|
||||
tool_log_filtered = self._tool_log if not self.ui_focus_agent else [
|
||||
e for e in self._tool_log if e.get("source_tier") == self.ui_focus_agent
|
||||
]
|
||||
clipper = imgui.ListClipper()
|
||||
clipper.begin(len(tool_log_filtered))
|
||||
while clipper.step():
|
||||
for i_minus_one in range(clipper.display_start, clipper.display_end):
|
||||
i = i_minus_one + 1
|
||||
entry = tool_log_filtered[i_minus_one]
|
||||
script = entry["script"]
|
||||
result = entry["result"]
|
||||
first_line = script.split('\n')[0] if script else 'Empty Script'
|
||||
imgui.text_colored(C_KEY, f"Call #{i}: {first_line}")
|
||||
# Script Display imgui.text_colored(C_LBL, "Script:")
|
||||
imgui.same_line()
|
||||
if imgui.button(f"[+]##script_{i}"):
|
||||
self.show_text_viewer = True
|
||||
self.text_viewer_title = f"Call Script #{i}"
|
||||
self.text_viewer_content = script
|
||||
if self.ui_word_wrap:
|
||||
imgui.begin_child(f"tc_script_wrap_{i}", imgui.ImVec2(-1, 72), True)
|
||||
imgui.push_text_wrap_pos(imgui.get_content_region_avail().x)
|
||||
imgui.text(script)
|
||||
imgui.pop_text_wrap_pos()
|
||||
imgui.end_child()
|
||||
else:
|
||||
imgui.begin_child(f"tc_script_fixed_width_{i}", imgui.ImVec2(0, 72), True, imgui.WindowFlags_.horizontal_scrollbar)
|
||||
imgui.input_text_multiline(f"##tc_script_res_{i}", script, imgui.ImVec2(-1, -1), imgui.InputTextFlags_.read_only)
|
||||
imgui.end_child()
|
||||
# Result Display
|
||||
imgui.text_colored(C_LBL, "Output:")
|
||||
imgui.same_line()
|
||||
if imgui.button(f"[+]##output_{i}"):
|
||||
self.show_text_viewer = True
|
||||
self.text_viewer_title = f"Call Output #{i}"
|
||||
self.text_viewer_content = result
|
||||
if self.ui_word_wrap:
|
||||
imgui.begin_child(f"tc_res_wrap_{i}", imgui.ImVec2(-1, 72), True)
|
||||
imgui.push_text_wrap_pos(imgui.get_content_region_avail().x)
|
||||
imgui.text(result)
|
||||
imgui.pop_text_wrap_pos()
|
||||
imgui.end_child()
|
||||
else:
|
||||
imgui.begin_child(f"tc_res_fixed_width_{i}", imgui.ImVec2(0, 72), True, imgui.WindowFlags_.horizontal_scrollbar)
|
||||
imgui.input_text_multiline(f"##tc_res_val_{i}", result, imgui.ImVec2(-1, -1), imgui.InputTextFlags_.read_only)
|
||||
imgui.end_child()
|
||||
imgui.separator()
|
||||
imgui.end_child()
|
||||
|
||||
log_to_render = self._tool_log_cache
|
||||
flags = imgui.TableFlags_.resizable | imgui.TableFlags_.hideable | imgui.TableFlags_.borders_inner_v | imgui.TableFlags_.row_bg | imgui.TableFlags_.scroll_y
|
||||
|
||||
if imgui.begin_table("tool_calls_table", 4, flags, imgui.ImVec2(0, 0)):
|
||||
imgui.table_setup_column("#", imgui.TableColumnFlags_.width_fixed, 40)
|
||||
imgui.table_setup_column("Tier", imgui.TableColumnFlags_.width_fixed, 60)
|
||||
imgui.table_setup_column("Script", imgui.TableColumnFlags_.width_stretch)
|
||||
imgui.table_setup_column("Result", imgui.TableColumnFlags_.width_fixed, 100)
|
||||
|
||||
imgui.table_headers_row()
|
||||
|
||||
clipper = imgui.ListClipper()
|
||||
clipper.begin(len(log_to_render))
|
||||
while clipper.step():
|
||||
for i in range(clipper.display_start, clipper.display_end):
|
||||
entry = log_to_render[i]
|
||||
imgui.table_next_row()
|
||||
|
||||
imgui.table_next_column()
|
||||
imgui.text_colored(C_LBL, f"#{i+1}")
|
||||
|
||||
imgui.table_next_column()
|
||||
imgui.text_colored(C_SUB, f"[{entry.get('source_tier', 'main')}]")
|
||||
|
||||
imgui.table_next_column()
|
||||
script = entry.get("script", "")
|
||||
script_preview = script.replace("\n", " ")[:150]
|
||||
if len(script) > 150: script_preview += "..."
|
||||
if imgui.selectable(f"{script_preview}##tc_{i}", False, imgui.SelectableFlags_.span_all_columns)[0]:
|
||||
self.text_viewer_title = f"Tool Script #{i+1}"
|
||||
self.text_viewer_content = script
|
||||
self.show_text_viewer = True
|
||||
|
||||
imgui.table_next_column()
|
||||
res = entry.get("result", "")
|
||||
res_preview = res.replace("\n", " ")[:30]
|
||||
if len(res) > 30: res_preview += "..."
|
||||
if imgui.button(f"View##res_{i}"):
|
||||
self.text_viewer_title = f"Call Output #{i+1}"
|
||||
self.text_viewer_content = res
|
||||
self.show_text_viewer = True
|
||||
|
||||
imgui.end_table()
|
||||
|
||||
if self._scroll_tool_calls_to_bottom:
|
||||
imgui.set_scroll_here_y(1.0)
|
||||
self._scroll_tool_calls_to_bottom = False
|
||||
|
||||
def _render_mma_dashboard(self) -> None:
|
||||
# Task 5.3: Dense Summary Line
|
||||
|
||||
Reference in New Issue
Block a user