Broken: Fixing this crap

This commit is contained in:
2026-05-12 17:47:46 -04:00
parent 7d8680232a
commit dc15d42ec7
+505 -409
View File
@@ -992,7 +992,7 @@ class App:
if p not in self.screenshots: self.screenshots.append(p)
return
def _gui_func__abusrd_try_scope(self) -> None:
def _render_main_interface(self) -> None:
self.perf_monitor.start_frame()
self._autofocus_response_tab = self.controller._autofocus_response_tab
@@ -1095,6 +1095,496 @@ class App:
else:
self._pending_dialog_open = False
if imgui.begin_popup_modal("Approve PowerShell Command", None, imgui.WindowFlags_.always_auto_resize)[0]:
if not dlg:
imgui.close_current_popup()
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."""
if not flag_condition or not self.show_windows.get(name, False): return
with imscope.window(name, self.show_windows[name]) as (exp, opened):
self.show_windows[name] = bool(opened)
if exp: render_func()
def _render_project_settings_hub(self) -> None:
with imscope.tab_bar('context_hub_tabs'):
with imscope.tab_item('Projects') as (exp, _):
if exp: self._render_projects_panel()
with imscope.tab_item('Paths') as (exp, _):
if exp: self._render_paths_panel()
def _render_ai_settings_hub(self) -> None:
self._render_persona_selector_panel()
if imgui.collapsing_header("Provider & Model"): self._render_provider_panel()
if imgui.collapsing_header("System Prompts"): self._render_system_prompts_panel()
if imgui.collapsing_header("RAG Settings"): self._render_rag_panel()
self._render_agent_tools_panel()
def _render_discussion_hub(self) -> None:
with imscope.tab_bar("discussion_hub_tabs"):
with imscope.tab_item("Discussion") as (exp, _):
if exp: self._render_discussion_tab()
with imscope.tab_item("Context Composition") as (exp, _):
if exp: self._render_context_composition_panel()
with imscope.tab_item("Snapshot") as (exp, _):
if exp: self._render_snapshot_tab()
with imscope.tab_item("Takes") as (exp, _):
if exp: self._render_takes_panel()
def _render_operations_hub(self) -> None:
imgui.push_style_var(imgui.StyleVar_.item_spacing, imgui.ImVec2(10, 4))
ch1, self.ui_separate_tool_calls_panel = imgui.checkbox("Pop Out Tool Calls", self.ui_separate_tool_calls_panel)
if ch1: self.show_windows["Tool Calls"] = self.ui_separate_tool_calls_panel
imgui.same_line()
ch2, self.ui_separate_usage_analytics = imgui.checkbox("Pop Out Usage Analytics", self.ui_separate_usage_analytics)
if ch2: self.show_windows["Usage Analytics"] = self.ui_separate_usage_analytics
imgui.same_line()
ch3, self.ui_separate_external_tools = imgui.checkbox('Pop Out External Tools', self.ui_separate_external_tools)
if ch3: self.show_windows['External Tools'] = self.ui_separate_external_tools
imgui.pop_style_var()
show_tc_tab, show_usage_tab = not self.ui_separate_tool_calls_panel, not self.ui_separate_usage_analytics
with imscope.tab_bar("ops_tabs"):
with imscope.tab_item("Comms History") as (exp, _):
if exp: self._render_comms_history_panel()
if show_tc_tab:
with imscope.tab_item("Tool Calls") as (exp, _):
if exp: self._render_tool_calls_panel()
if show_usage_tab:
with imscope.tab_item("Usage Analytics") as (exp, _):
if exp: self._render_usage_analytics_panel()
if not self.ui_separate_external_tools:
with imscope.tab_item("External Tools") as (exp, _):
if exp:
self._render_external_tools_panel()
imgui.separator(); imgui.text("")
try: self._render_external_editor_panel()
except Exception as e: imgui.text_colored(vec4(1, 0.3, 0.3, 1), f"Error: {str(e)}")
with imscope.tab_item("Workspace Layouts") as (exp, _):
if exp:
imgui.text("Experimental: Auto-switch layout by Tier")
ch, self.controller.ui_auto_switch_layout = imgui.checkbox("Enable Auto-Switch", self.controller.ui_auto_switch_layout)
if self.controller.ui_auto_switch_layout:
imgui.separator(); imgui.text("Tier Bindings (select profile for each tier)")
profiles = [""] + [p.name for p in self.controller.workspace_profiles.values()]
for t in ["Tier 1", "Tier 2", "Tier 3", "Tier 4"]:
curr = self.controller.ui_tier_layout_bindings.get(t, ""); idx = profiles.index(curr) if curr in profiles else 0
ch_combo, new_idx = imgui.combo(t, idx, profiles)
if ch_combo: self.controller.ui_tier_layout_bindings[t] = profiles[new_idx]
def _render_thinking_indicator(self) -> None:
is_thinking = self.ai_status in ['sending...', 'streaming...', 'running powershell...']
if is_thinking:
val = math.sin(time.time() * 10 * math.pi)
alpha = 1.0 if val > 0 else 0.0
c = vec4(255, 50, 50, alpha) if theme.is_nerv_active() else vec4(255, 100, 100, alpha)
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:
if not imgui.collapsing_header("Discussions", imgui.TreeNodeFlags_.default_open): return
names = self._get_discussion_names(); grouped = {}
for name in names:
base = name.split("_take_")[0]; grouped.setdefault(base, []).append(name)
active_base = self.active_discussion.split("_take_")[0]
if active_base not in grouped: active_base = names[0] if names else ""
base_names = sorted(grouped.keys())
if imgui.begin_combo("##disc_sel", active_base):
for bname in base_names:
is_selected = (bname == active_base)
if imgui.selectable(bname, is_selected)[0]:
target = bname if bname in names else grouped[bname][0]
if target != self.active_discussion: self._switch_discussion(target)
if is_selected: imgui.set_item_default_focus()
imgui.end_combo()
active_base = self.active_discussion.split("_take_")[0]; current_takes = grouped.get(active_base, [])
if imgui.begin_tab_bar("discussion_takes_tabs"):
for take_name in current_takes:
label = "Original" if take_name == active_base else take_name.replace(f"{active_base}_", "").replace("_", " ").title()
flags = imgui.TabItemFlags_.set_selected if take_name == self.active_discussion else 0
with imscope.tab_item(f"{label}###{take_name}", flags) as (exp, _):
if exp and take_name != self.active_discussion: self._switch_discussion(take_name)
with imscope.tab_item("Synthesis###Synthesis") as (exp, _):
if exp: self._render_synthesis_panel()
imgui.end_tab_bar()
if "_take_" in self.active_discussion:
if imgui.button("Promote Take"):
base_name = self.active_discussion.split("_take_")[0]; new_name = f"{base_name}_promoted"; counter = 1
while new_name in names: new_name = f"{base_name}_promoted_{counter}"; counter += 1
project_manager.promote_take(self.project, self.active_discussion, new_name); self._switch_discussion(new_name)
imgui.same_line()
if self.active_track:
imgui.same_line(); ch, self._track_discussion_active = imgui.checkbox("Track Discussion", self._track_discussion_active)
if ch:
if self._track_discussion_active:
self._flush_disc_entries_to_project()
history_strings = project_manager.load_track_history(self.active_track.id, self.active_project_root)
with self._disc_entries_lock: self.disc_entries = models.parse_history_entries(history_strings, self.disc_roles)
self.ai_status = f"track discussion: {self.active_track.id}"
else: self._flush_disc_entries_to_project(); self._switch_discussion(self.active_discussion); self.ai_status = "track discussion disabled"
self._render_discussion_metadata()
def _render_discussion_metadata(self) -> None:
disc_data = self.project.get("discussion", {}).get("discussions", {}).get(self.active_discussion, {})
git_commit, last_updated = disc_data.get("git_commit", ""), disc_data.get("last_updated", "")
imgui.text_colored(C_LBL, "commit:"); imgui.same_line()
self._render_selectable_label('git_commit_val', git_commit[:12] if git_commit else '(none)', width=100, color=(C_IN if git_commit else C_LBL))
imgui.same_line()
if imgui.button("Update Commit"):
if self.ui_project_git_dir:
cmt = project_manager.get_git_commit(self.ui_project_git_dir)
if cmt: disc_data["git_commit"], disc_data["last_updated"], self.ai_status = cmt, project_manager.now_ts(), f"commit: {cmt[:12]}"
imgui.text_colored(C_LBL, "updated:"); imgui.same_line(); imgui.text_colored(C_SUB, last_updated if last_updated else "(never)")
ch, self.ui_disc_new_name_input = imgui.input_text("##new_disc", self.ui_disc_new_name_input); imgui.same_line()
if imgui.button("Create"):
nm = self.ui_disc_new_name_input.strip()
if nm: self._create_discussion(nm); self.ui_disc_new_name_input = ""
imgui.same_line()
if imgui.button("Rename"):
nm = self.ui_disc_new_name_input.strip()
if nm: self._rename_discussion(self.active_discussion, nm); self.ui_disc_new_name_input = ""
imgui.same_line()
if imgui.button("Delete"): self._delete_discussion(self.active_discussion)
def _render_discussion_entry_controls(self) -> None:
if imgui.button("+ Entry"): self.disc_entries.append({"role": self.disc_roles[0] if self.disc_roles else "User", "content": "", "collapsed": True, "ts": project_manager.now_ts()})
imgui.same_line()
if imgui.button("-All"):
for e in self.disc_entries: e["collapsed"] = True
imgui.same_line()
if imgui.button("+All"):
for e in self.disc_entries: e["collapsed"] = False
imgui.same_line()
if imgui.button("Clear All"): self.disc_entries.clear()
imgui.same_line()
if imgui.button("Save"): self._flush_to_project(); self._flush_to_config(); models.save_config(self.config); self.ai_status = "discussion saved"
_, self.ui_auto_add_history = imgui.checkbox("Auto-add message & response to history", self.ui_auto_add_history)
imgui.text("Keep Pairs:"); imgui.same_line(); imgui.set_next_item_width(80)
ch, self.ui_disc_truncate_pairs = imgui.input_int("##trunc_pairs", self.ui_disc_truncate_pairs, 1)
if self.ui_disc_truncate_pairs < 1: self.ui_disc_truncate_pairs = 1
imgui.same_line()
if imgui.button("Truncate"):
with self._disc_entries_lock: self.disc_entries = truncate_entries(self.disc_entries, self.ui_disc_truncate_pairs)
self.ai_status = f"history truncated to {self.ui_disc_truncate_pairs} pairs"
def _render_discussion_roles(self) -> None:
if imgui.collapsing_header("Roles"):
with imscope.child("roles_scroll", size_y=100, flags=True):
for i, r in enumerate(list(self.disc_roles)):
with imscope.id(f"role_{i}"):
if imgui.button("X"): self.disc_roles.pop(i); break
imgui.same_line(); imgui.text(r)
ch, self.ui_disc_new_role_input = imgui.input_text("##new_role", self.ui_disc_new_role_input); imgui.same_line()
if imgui.button("Add"):
r = self.ui_disc_new_role_input.strip()
if r and r not in self.disc_roles: self.disc_roles.append(r); self.ui_disc_new_role_input = ""
def _render_discussion_entries(self) -> None:
with imscope.child("disc_scroll"):
display_entries = self.disc_entries
if self.ui_focus_agent:
tier_usage = self.mma_tier_usage.get(self.ui_focus_agent)
if tier_usage:
persona_name = tier_usage.get("persona")
if persona_name: display_entries = [e for e in self.disc_entries if e.get("role") == persona_name or e.get("role") == "User"]
clipper = imgui.ListClipper(); clipper.begin(len(display_entries))
while clipper.step():
for i in range(clipper.display_start, clipper.display_end):
self._render_discussion_entry(display_entries[i], i)
if self._scroll_disc_to_bottom: imgui.set_scroll_here_y(1.0); self._scroll_disc_to_bottom = False
def _render_discussion_entry(self, entry: dict, index: int) -> None:
with imscope.id(f"disc_{index}"):
collapsed, read_mode = entry.get("collapsed", False), entry.get("read_mode", False)
if imgui.button("+" if collapsed else "-"): entry["collapsed"] = not collapsed
imgui.same_line(); self._render_text_viewer(f"Entry #{index+1}", entry["content"]); imgui.same_line(); imgui.set_next_item_width(120)
if imgui.begin_combo("##role", entry["role"]):
for r in self.disc_roles:
if imgui.selectable(r, r == entry["role"])[0]: entry["role"] = r
imgui.end_combo()
if not collapsed:
imgui.same_line()
if imgui.button("[Edit]" if read_mode else "[Read]"): entry["read_mode"] = not read_mode
ts_str = entry.get("ts", "")
if ts_str:
imgui.same_line(); imgui.text_colored(vec4(120, 120, 100), str(ts_str)); e_dt = project_manager.parse_ts(ts_str)
if e_dt:
e_unix, next_unix = e_dt.timestamp(), float('inf')
if index + 1 < len(self.disc_entries):
n_ts = self.disc_entries[index+1].get("ts", ""); n_dt = project_manager.parse_ts(n_ts)
if n_dt: next_unix = n_dt.timestamp()
injected = [f for f in self.files if hasattr(f, 'injected_at') and f.injected_at and e_unix <= f.injected_at < next_unix]
if injected:
imgui.same_line(); imgui.text_colored(vec4(100, 255, 100), f"[{len(injected)}+]")
if imgui.is_item_hovered(): imgui.set_tooltip("Files injected at this point:\n" + "\n".join([f.path for f in injected]))
if collapsed:
imgui.same_line()
if imgui.button("Ins"): self.disc_entries.insert(index, {"role": "User", "content": "", "collapsed": True, "ts": project_manager.now_ts()})
imgui.same_line()
if imgui.button("Del"): self.disc_entries.pop(index); return
imgui.same_line()
if imgui.button("Branch"): self._branch_discussion(index)
imgui.same_line(); preview = entry["content"].replace("\n", " ")[:60]
if len(entry["content"]) > 60: preview += "..."
if not preview.strip() and entry.get("thinking_segments"):
preview = entry["thinking_segments"][0]["content"].replace("\n", " ")[:60]
if len(entry["thinking_segments"][0]["content"]) > 60: preview += "..."
imgui.text_colored(vec4(160, 160, 150), preview)
if not collapsed:
thinking_segments, has_content = entry.get("thinking_segments", []), bool(entry.get("content", "").strip())
if thinking_segments: self._render_thinking_trace(thinking_segments, index, is_standalone=not has_content)
if read_mode: self._render_discussion_entry_read_mode(entry, index)
else:
if not (bool(thinking_segments) and not has_content): ch, entry["content"] = imgui.input_text_multiline("##content", entry["content"], imgui.ImVec2(-1, 150))
imgui.separator()
def _render_discussion_entry_read_mode(self, entry: dict, index: int) -> None:
content = entry["content"]
if not content.strip(): return
if '## Retrieved Context' in content:
rag_match = re.search(r'## Retrieved Context\n\n([\s\S]*?)(?=\n\n#|\Z)', content)
if rag_match:
rag_section = rag_match.group(1)
if imgui.collapsing_header('Retrieved Context'):
chunks = re.finditer(r'### Chunk (\d+) \(Source: (.*?)\)\n([\s\S]*?)(?=\n### Chunk|\Z)', rag_section)
for chunk_match in chunks:
idx, path, chunk_content = chunk_match.group(1), chunk_match.group(2), chunk_match.group(3)
if imgui.collapsing_header(f'Chunk {idx}: {path}'):
if imgui.button(f'[Source]##rag_{index}_{idx}'):
res = mcp_client.read_file(path)
if res: self.text_viewer_title, self.text_viewer_content, self.text_viewer_type, self.show_text_viewer = path, res, (Path(path).suffix.lstrip('.') if Path(path).suffix else 'text'), True
imgui.text_unformatted(chunk_content)
content = content[:rag_match.start()] + content[rag_match.end():]
pattern = re.compile(r"\[Definition: (.*?) from (.*?) \(line (\d+)\)\](\s+```[\s\S]*?```)?")
matches, is_nerv = list(pattern.finditer(content)), theme.is_nerv_active()
if not matches:
if is_nerv: imgui.push_style_color(imgui.Col_.text, vec4(80, 255, 80))
markdown_helper.render(content, context_id=f'disc_{index}')
if is_nerv: imgui.pop_style_color()
else:
with imscope.child(f"read_content_{index}", size_y=150, flags=True):
if self.ui_word_wrap: imgui.push_text_wrap_pos(imgui.get_content_region_avail().x)
last_idx = 0
for m_idx, match in enumerate(matches):
before = content[last_idx:match.start()]
if before:
if is_nerv: imgui.push_style_color(imgui.Col_.text, vec4(80, 255, 80))
markdown_helper.render(before, context_id=f'disc_{index}_b_{m_idx}')
if is_nerv: imgui.pop_style_color()
header_text, path, code_block = match.group(0).split("\n")[0].strip(), match.group(2), match.group(4)
if imgui.collapsing_header(header_text):
if imgui.button(f"[Source]##{index}_{match.start()}"):
res = mcp_client.read_file(path)
if res: self.text_viewer_title, self.text_viewer_content, self.text_viewer_type, self.show_text_viewer = path, res, (Path(path).suffix.lstrip('.') if Path(path).suffix else 'text'), True
if code_block:
if is_nerv: imgui.push_style_color(imgui.Col_.text, vec4(80, 255, 80))
markdown_helper.render(code_block, context_id=f'disc_{index}_c_{m_idx}')
if is_nerv: imgui.pop_style_color()
last_idx = match.end()
after = content[last_idx:]
if after:
if is_nerv: imgui.push_style_color(imgui.Col_.text, vec4(80, 255, 80))
markdown_helper.render(after, context_id=f'disc_{index}_a')
if is_nerv: imgui.pop_style_color()
if self.ui_word_wrap: imgui.pop_text_wrap_pos()
def _render_mma_focus_selector(self) -> None:
imgui.text("Focus Agent:"); imgui.same_line()
focus_label = self.ui_focus_agent or "All"
if imgui.begin_combo("##focus_agent", focus_label, imgui.ComboFlags_.width_fit_preview):
if imgui.selectable("All", self.ui_focus_agent is None)[0]: self.ui_focus_agent = None
for tier in ["Tier 2", "Tier 3", "Tier 4"]:
if imgui.selectable(tier, self.ui_focus_agent == tier)[0]: self.ui_focus_agent = tier
imgui.end_combo()
imgui.same_line()
if self.ui_focus_agent and imgui.button("x##clear_focus"): self.ui_focus_agent = None
def _render_mma_track_summary(self) -> None:
is_nerv = theme.is_nerv_active()
track_name = self.active_track.description if self.active_track else "None"
if getattr(self, "ui_project_execution_mode", "native") == "beads": track_name = "Beads Graph"
track_stats = project_manager.calculate_track_progress(self.active_track.tickets if self.active_track else self.active_tickets)
total_cost = sum(cost_tracker.estimate_cost(u.get('model','unknown'), u.get('input',0), u.get('output',0)) for u in self.mma_tier_usage.values())
imgui.text("Track:"); imgui.same_line(); imgui.text_colored(C_VAL, track_name); imgui.same_line(); imgui.text(" | Status:"); imgui.same_line()
if self.mma_status == "paused":
imgui.text_colored(vec4(255, 152, 48) if is_nerv else imgui.ImVec4(1, 0.5, 0, 1), "PIPELINE PAUSED"); imgui.same_line()
status_col = imgui.ImVec4(1, 1, 1, 1)
if self.mma_status == "idle": status_col = imgui.ImVec4(0.7, 0.7, 0.7, 1)
elif self.mma_status == "running": status_col = vec4(80, 255, 80) if is_nerv else imgui.ImVec4(1, 1, 0, 1)
elif self.mma_status == "done": status_col = imgui.ImVec4(0, 1, 0, 1)
elif self.mma_status == "error": status_col = vec4(255, 72, 64) if is_nerv else imgui.ImVec4(1, 0, 0, 1)
elif self.mma_status == "paused": status_col = imgui.ImVec4(1, 0.5, 0, 1)
imgui.text_colored(status_col, self.mma_status.upper()); imgui.same_line(); imgui.text(" | Cost:"); imgui.same_line(); imgui.text_colored(imgui.ImVec4(0, 1, 0, 1), f"${total_cost:,.4f}")
perc = track_stats["percentage"] / 100.0
p_color = imgui.ImVec4(1, 0, 0, 1) if track_stats["percentage"] < 33 else (imgui.ImVec4(1, 1, 0, 1) if track_stats["percentage"] < 66 else imgui.ImVec4(0, 1, 0, 1))
imgui.push_style_color(imgui.Col_.plot_histogram, p_color); imgui.progress_bar(perc, imgui.ImVec2(-1, 0), f"{track_stats['percentage']:.1f}%"); imgui.pop_style_color()
if imgui.begin_table("ticket_stats_breakdown", 4):
for lbl, val in [("Completed:", track_stats["completed"]), ("In Progress:", track_stats["in_progress"]), ("Blocked:", track_stats["blocked"]), ("Todo:", track_stats["todo"])]:
imgui.table_next_column(); imgui.text_colored(C_LBL, lbl); imgui.same_line(); imgui.text_colored(C_VAL, str(val))
imgui.end_table()
if self.active_track:
remaining = track_stats["total"] - track_stats["completed"]
eta_mins = (self._avg_ticket_time * remaining) / 60.0
imgui.text_colored(C_LBL, "ETA:"); imgui.same_line(); imgui.text_colored(C_VAL, f"~{int(eta_mins)}m ({remaining} tickets remaining)")
def _render_mma_epic_planner(self) -> None:
imgui.text_colored(C_LBL, 'Epic Planning (Tier 1)')
_, self.ui_epic_input = imgui.input_text_multiline('##epic_input', self.ui_epic_input, imgui.ImVec2(-1, 80))
if imgui.button('Plan Epic (Tier 1)', imgui.ImVec2(-1, 0)): self._cb_plan_epic()
def _render_mma_conductor_setup(self) -> None:
if imgui.button("Run Setup Scan"): self._cb_run_conductor_setup()
if self.ui_conductor_setup_summary: imgui.input_text_multiline("##setup_summary", self.ui_conductor_setup_summary, imgui.ImVec2(-1, 120), imgui.InputTextFlags_.read_only)
def _render_mma_track_browser(self) -> None:
imgui.text("Track Browser")
if imgui.begin_table("mma_tracks_table", 4, imgui.TableFlags_.borders | imgui.TableFlags_.row_bg | imgui.TableFlags_.resizable):
imgui.table_setup_column("Title"); imgui.table_setup_column("Status"); imgui.table_setup_column("Progress"); imgui.table_setup_column("Actions"); imgui.table_headers_row()
for track in self.tracks:
imgui.table_next_row(); imgui.table_next_column(); imgui.text(track.get("title", "Untitled")); imgui.table_next_column()
status = track.get("status", "unknown").lower()
c = imgui.ImVec4(0.7, 0.7, 0.7, 1) if status == "new" else (vec4(80, 255, 80) if status == "active" and theme.is_nerv_active() else (imgui.ImVec4(1, 1, 0, 1) if status == "active" else (imgui.ImVec4(0, 1, 0, 1) if status == "done" else (imgui.ImVec4(1, 0, 0, 1) if status == "blocked" else imgui.ImVec4(1, 1, 1, 1)))))
imgui.text_colored(c, status.upper()); imgui.table_next_column()
prog = track.get("progress", 0.0)
p_c = imgui.ImVec4(1, 0, 0, 1) if prog < 0.33 else (imgui.ImVec4(1, 1, 0, 1) if prog < 0.66 else imgui.ImVec4(0, 1, 0, 1))
imgui.push_style_color(imgui.Col_.plot_histogram, p_c); imgui.progress_bar(prog, imgui.ImVec2(-1, 0), f"{int(prog*100)}%"); imgui.pop_style_color(); imgui.table_next_column()
if imgui.button(f"Load##{track.get('id')}"): self._cb_load_track(str(track.get("id") or ""))
imgui.end_table()
imgui.text("Create New Track")
_, self.ui_new_track_name = imgui.input_text("Name##new_track", self.ui_new_track_name)
_, self.ui_new_track_desc = imgui.input_text_multiline("Description##new_track", self.ui_new_track_desc, imgui.ImVec2(-1, 60))
imgui.text("Type:"); imgui.same_line()
if imgui.begin_combo("##track_type", self.ui_new_track_type):
for ttype in ["feature", "chore", "fix"]:
if imgui.selectable(ttype, self.ui_new_track_type == ttype)[0]: self.ui_new_track_type = ttype
imgui.end_combo()
if imgui.button("Create Track"):
self._cb_create_track(self.ui_new_track_name, self.ui_new_track_desc, self.ui_new_track_type)
self.ui_new_track_name = ""; self.ui_new_track_desc = ""
def _render_mma_global_controls(self) -> None:
changed, self.mma_step_mode = imgui.checkbox("Step Mode (HITL)", self.mma_step_mode)
imgui.same_line(); imgui.text(f"Status: {self.mma_status.upper()}")
if self.controller and hasattr(self.controller, 'engine') and self.controller.engine and hasattr(self.controller.engine, '_pause_event'):
imgui.same_line()
is_paused = self.controller.engine._pause_event.is_set()
if imgui.button("Resume" if is_paused else "Pause"):
if is_paused: self.controller.engine.resume()
else: self.controller.engine.pause()
if self.active_tier:
imgui.same_line(); imgui.text_colored(C_VAL, f"| Active: {self.active_tier}")
any_pending = len(self._pending_mma_spawns) > 0 or len(self._pending_mma_approvals) > 0 or self._pending_ask_dialog
if any_pending:
alpha = abs(math.sin(time.time() * 5))
c = vec4(255, 72, 64, alpha) if theme.is_nerv_active() else imgui.ImVec4(1, 0.3, 0.3, alpha)
imgui.same_line(); imgui.text_colored(c, " APPROVAL PENDING"); imgui.same_line()
if imgui.button("Go to Approval"): pass
def _render_mma_usage_section(self) -> None:
imgui.text("Tier Usage (Tokens & Cost)")
if imgui.begin_table("mma_usage", 5, imgui.TableFlags_.borders | imgui.TableFlags_.row_bg):
imgui.table_setup_column("Tier"); imgui.table_setup_column("Model"); imgui.table_setup_column("Input"); imgui.table_setup_column("Output"); imgui.table_setup_column("Est. Cost"); imgui.table_headers_row()
total_cost = 0.0
for tier, stats in self.mma_tier_usage.items():
imgui.table_next_row(); imgui.table_next_column(); imgui.text(tier); imgui.table_next_column(); model = stats.get('model', 'unknown'); imgui.text(model); imgui.table_next_column(); in_t = stats.get('input', 0); imgui.text(f"{in_t:,}"); imgui.table_next_column(); out_t = stats.get('output', 0); imgui.text(f"{out_t:,}"); imgui.table_next_column(); cost = cost_tracker.estimate_cost(model, in_t, out_t); total_cost += cost; imgui.text(f"${cost:,.4f}")
imgui.table_next_row(); imgui.table_set_bg_color(imgui.TableBgTarget_.row_bg0, imgui.get_color_u32(imgui.Col_.plot_lines_hovered)); imgui.table_next_column(); imgui.text("TOTAL"); imgui.table_next_column(); imgui.text(""); imgui.table_next_column(); imgui.text(""); imgui.table_next_column(); imgui.text(""); imgui.table_next_column(); imgui.text(f"${total_cost:,.4f}"); imgui.end_table()
if imgui.collapsing_header("Tier Model Config"):
for tier in self.mma_tier_usage.keys():
imgui.text(f"{tier}:"); imgui.same_line(); curr_model, curr_prov = self.mma_tier_usage[tier].get("model", "unknown"), self.mma_tier_usage[tier].get("provider", "gemini")
with imscope.id(f"tier_cfg_{tier}"):
imgui.push_item_width(80)
if imgui.begin_combo("##prov", curr_prov):
for p in models.PROVIDERS:
if imgui.selectable(p, p == curr_prov)[0]:
self.mma_tier_usage[tier]["provider"] = p
models_list = self.controller.all_available_models.get(p, [])
if models_list: self.mma_tier_usage[tier]["model"] = models_list[0]
imgui.end_combo()
imgui.pop_item_width(); imgui.same_line(); imgui.push_item_width(150)
models_list = self.controller.all_available_models.get(curr_prov, [])
if imgui.begin_combo("##model", curr_model):
for m in models_list:
if imgui.selectable(m, curr_model == m)[0]: self.mma_tier_usage[tier]["model"] = m
imgui.end_combo()
imgui.pop_item_width(); imgui.same_line(); imgui.push_item_width(-1)
curr_preset = self.mma_tier_usage[tier].get("tool_preset") or "None"
p_names = ["None"] + sorted(self.controller.tool_presets.keys())
if imgui.begin_combo("##preset", curr_preset):
for pn in p_names:
if imgui.selectable(pn, curr_preset == pn)[0]: self.mma_tier_usage[tier]["tool_preset"] = None if pn == "None" else pn
imgui.end_combo()
imgui.pop_item_width(); imgui.same_line(); imgui.push_item_width(150)
curr_pers = self.mma_tier_usage[tier].get("persona") or "None"
personas = getattr(self.controller, 'personas', {})
pers_opts = ["None"] + sorted(personas.keys())
if imgui.begin_combo("##persona", curr_pers):
for pern in pers_opts:
if imgui.selectable(pern, curr_pers == pern)[0]: self.mma_tier_usage[tier]["persona"] = None if pern == "None" else pern
imgui.end_combo()
imgui.pop_item_width()
def _render_mma_ticket_editor(self) -> None:
imgui.separator(); imgui.text_colored(C_VAL, f"Editing: {self.ui_selected_ticket_id}")
ticket = next((t for t in self.active_tickets if str(t.get('id', '')) == self.ui_selected_ticket_id), None)
if ticket:
imgui.text(f"Status: {ticket.get('status', 'todo')}"); prio = ticket.get('priority', 'medium')
imgui.text("Priority:"); imgui.same_line()
if imgui.begin_combo(f"##edit_prio_{ticket.get('id')}", prio):
for p_opt in ['high', 'medium', 'low']:
if imgui.selectable(p_opt, p_opt == prio)[0]: ticket['priority'] = p_opt; self._push_mma_state_update()
imgui.end_combo()
imgui.text(f"Target: {ticket.get('target_file', '')}"); imgui.text(f"Depends on: {', '.join(ticket.get('depends_on', []))}")
personas = getattr(self.controller, 'personas', {}); curr_pers = ticket.get('persona_id', '')
imgui.text("Persona Override:"); imgui.same_line()
pers_opts = ["None"] + sorted(personas.keys()); curr_idx = pers_opts.index(curr_pers) + 1 if curr_pers in pers_opts else 0
_, curr_idx = imgui.combo(f"##ticket_persona_{ticket.get('id')}", curr_idx, pers_opts)
ticket['persona_id'] = None if curr_idx == 0 or pers_opts[curr_idx] == "None" else pers_opts[curr_idx]
if imgui.button(f"Mark Complete##{self.ui_selected_ticket_id}"): ticket['status'] = 'done'; self._push_mma_state_update()
imgui.same_line()
if imgui.button(f"Delete##{self.ui_selected_ticket_id}"): self.active_tickets = [t for t in self.active_tickets if str(t.get('id', '')) != self.ui_selected_ticket_id]; self.ui_selected_ticket_id = None; self._push_mma_state_update()
def _render_mma_agent_streams(self) -> None:
imgui.text("Agent Streams")
if imgui.begin_tab_bar("mma_streams_tabs"):
for tier, label, sep_flag_attr in [("Tier 1", "Tier 1", "ui_separate_tier1"), ("Tier 2", "Tier 2 (Tech Lead)", "ui_separate_tier2"), ("Tier 3", None, "ui_separate_tier3"), ("Tier 4", "Tier 4 (QA)", "ui_separate_tier4")]:
with imscope.tab_item(tier) as (exp, _):
if exp:
sep_val = getattr(self, sep_flag_attr); ch, new_val = imgui.checkbox(f"Pop Out {tier}", sep_val)
if ch:
setattr(self, sep_flag_attr, new_val)
self.show_windows[f"{tier}: Strategy" if tier == "Tier 1" else (f"{tier}: Tech Lead" if tier == "Tier 2" else (f"{tier}: Workers" if tier == "Tier 3" else f"{tier}: QA"))] = new_val
if not new_val: self._render_tier_stream_panel(tier, label)
else: imgui.text_disabled(f"{tier} stream is detached.")
if getattr(self, "ui_project_execution_mode", "native") == "beads":
with imscope.tab_item("Beads") as (exp, _):
if exp: self._render_beads_tab()
imgui.end_tab_bar()
if imgui.begin_popup_modal("Approve PowerShell Command", None, imgui.WindowFlags_.always_auto_resize)[0]:
if not dlg:
imgui.close_current_popup()
@@ -4693,429 +5183,35 @@ def hello():
imgui.end_table()
def _render_mma_dashboard(self) -> None:
"""
[C: tests/test_gui_progress.py:test_render_mma_dashboard_progress, tests/test_mma_approval_indicators.py:TestMMAApprovalIndicators.test_approval_badge_shown_when_ask_dialog_pending, tests/test_mma_approval_indicators.py:TestMMAApprovalIndicators.test_approval_badge_shown_when_mma_approval_pending, tests/test_mma_approval_indicators.py:TestMMAApprovalIndicators.test_approval_badge_shown_when_spawn_pending, tests/test_mma_approval_indicators.py:TestMMAApprovalIndicators.test_no_approval_badge_when_idle]
"""
"""Main MMA dashboard interface."""
if self.perf_profiling_enabled: self.perf_monitor.start_component("_render_mma_dashboard")
# Focus Agent dropdown
imgui.text("Focus Agent:")
imgui.same_line()
focus_label = self.ui_focus_agent or "All"
if imgui.begin_combo("##focus_agent", focus_label, imgui.ComboFlags_.width_fit_preview):
if imgui.selectable("All", self.ui_focus_agent is None)[0]:
self.ui_focus_agent = None
for tier in ["Tier 2", "Tier 3", "Tier 4"]:
if imgui.selectable(tier, self.ui_focus_agent == tier)[0]:
self.ui_focus_agent = tier
imgui.end_combo()
imgui.same_line()
if self.ui_focus_agent:
if imgui.button("x##clear_focus"):
self.ui_focus_agent = None
self._render_mma_focus_selector()
imgui.separator()
is_nerv = theme.is_nerv_active()
if self.is_viewing_prior_session:
c = vec4(255, 200, 100)
if is_nerv: c = vec4(255, 152, 48) # NERV_ORANGE
c = vec4(255, 152, 48) if theme.is_nerv_active() else vec4(255, 200, 100)
imgui.text_colored(c, "HISTORICAL VIEW - READ ONLY")
if self.perf_profiling_enabled: self.perf_monitor.end_component("_render_mma_dashboard")
return
# Task 5.3: Dense Summary Line
track_name = self.active_track.description if self.active_track else "None"
if getattr(self, "ui_project_execution_mode", "native") == "beads":
track_name = "Beads Graph"
track_stats = {"percentage": 0.0, "completed": 0, "total": 0, "in_progress": 0, "blocked": 0, "todo": 0}
if self.active_track:
track_stats = project_manager.calculate_track_progress(self.active_track.tickets)
elif self.active_tickets:
track_stats = project_manager.calculate_track_progress(self.active_tickets)
total_cost = 0.0
for usage in self.mma_tier_usage.values():
model = usage.get('model', 'unknown')
in_t = usage.get('input', 0)
out_t = usage.get('output', 0)
total_cost += cost_tracker.estimate_cost(model, in_t, out_t)
imgui.text("Track:")
imgui.same_line()
imgui.text_colored(C_VAL, track_name)
imgui.same_line()
imgui.text(" | Status:")
imgui.same_line()
if self.mma_status == "paused":
c = imgui.ImVec4(1, 0.5, 0, 1)
if is_nerv: c = vec4(255, 152, 48)
imgui.text_colored(c, "PIPELINE PAUSED")
imgui.same_line()
status_col = imgui.ImVec4(1, 1, 1, 1)
if self.mma_status == "idle": status_col = imgui.ImVec4(0.7, 0.7, 0.7, 1)
elif self.mma_status == "running": status_col = imgui.ImVec4(1, 1, 0, 1)
elif self.mma_status == "done": status_col = imgui.ImVec4(0, 1, 0, 1)
elif self.mma_status == "error": status_col = imgui.ImVec4(1, 0, 0, 1)
elif self.mma_status == "paused": status_col = imgui.ImVec4(1, 0.5, 0, 1)
if is_nerv:
if self.mma_status == "running": status_col = vec4(80, 255, 80) # DATA_GREEN
elif self.mma_status == "error": status_col = vec4(255, 72, 64) # ALERT_RED
imgui.text_colored(status_col, self.mma_status.upper())
imgui.same_line()
imgui.text(" | Cost:")
imgui.same_line()
imgui.text_colored(imgui.ImVec4(0, 1, 0, 1), f"${total_cost:,.4f}")
# Progress Bar
perc = track_stats["percentage"] / 100.0
p_color = imgui.ImVec2(0.0, 1.0) # WAIT WRONG TYPE
p_color = imgui.ImVec4(0.0, 1.0, 0.0, 1.0)
if track_stats["percentage"] < 33:
p_color = imgui.ImVec4(1.0, 0.0, 0.0, 1.0)
elif track_stats["percentage"] < 66:
p_color = imgui.ImVec4(1.0, 1.0, 0.0, 1.0)
imgui.push_style_color(imgui.Col_.plot_histogram, p_color)
imgui.progress_bar(perc, imgui.ImVec2(-1, 0), f"{track_stats['percentage']:.1f}%")
imgui.pop_style_color()
# Detailed breakdown
if imgui.begin_table("ticket_stats_breakdown", 4):
imgui.table_next_column()
imgui.text_colored(C_LBL, "Completed:")
imgui.same_line()
imgui.text_colored(C_VAL, str(track_stats["completed"]))
imgui.table_next_column()
imgui.text_colored(C_LBL, "In Progress:")
imgui.same_line()
imgui.text_colored(C_VAL, str(track_stats["in_progress"]))
imgui.table_next_column()
imgui.text_colored(C_LBL, "Blocked:")
imgui.same_line()
imgui.text_colored(C_VAL, str(track_stats["blocked"]))
imgui.table_next_column()
imgui.text_colored(C_LBL, "Todo:")
imgui.same_line()
imgui.text_colored(C_VAL, str(track_stats["todo"]))
imgui.end_table()
if self.active_track:
remaining = track_stats["total"] - track_stats["completed"]
eta_mins = (self._avg_ticket_time * remaining) / 60.0
imgui.text_colored(C_LBL, "ETA:")
imgui.same_line()
imgui.text_colored(C_VAL, f"~{int(eta_mins)}m ({remaining} tickets remaining)")
self._render_mma_track_summary()
imgui.separator()
imgui.text_colored(C_LBL, 'Epic Planning (Tier 1)')
_, self.ui_epic_input = imgui.input_text_multiline('##epic_input', self.ui_epic_input, imgui.ImVec2(-1, 80))
if imgui.button('Plan Epic (Tier 1)', imgui.ImVec2(-1, 0)):
self._cb_plan_epic()
self._render_mma_epic_planner()
imgui.separator()
# 0. Conductor Setup
if imgui.collapsing_header("Conductor Setup"):
if imgui.button("Run Setup Scan"):
self._cb_run_conductor_setup()
if self.ui_conductor_setup_summary:
imgui.input_text_multiline("##setup_summary", self.ui_conductor_setup_summary, imgui.ImVec2(-1, 120), imgui.InputTextFlags_.read_only)
if imgui.collapsing_header("Conductor Setup"): self._render_mma_conductor_setup()
imgui.separator()
# 1. Track Browser
imgui.text("Track Browser")
if imgui.begin_table("mma_tracks_table", 4, imgui.TableFlags_.borders | imgui.TableFlags_.row_bg | imgui.TableFlags_.resizable):
imgui.table_setup_column("Title")
imgui.table_setup_column("Status")
imgui.table_setup_column("Progress")
imgui.table_setup_column("Actions")
imgui.table_headers_row()
for track in self.tracks:
imgui.table_next_row()
imgui.table_next_column()
imgui.text(track.get("title", "Untitled"))
imgui.table_next_column()
status = track.get("status", "unknown").lower()
if status == "new":
imgui.text_colored(imgui.ImVec4(0.7, 0.7, 0.7, 1.0), "NEW")
elif status == "active":
c = imgui.ImVec4(1.0, 1.0, 0.0, 1.0)
if is_nerv: c = vec4(80, 255, 80)
imgui.text_colored(c, "ACTIVE")
elif status == "done":
imgui.text_colored(imgui.ImVec4(0.0, 1.0, 0.0, 1.0), "DONE")
elif status == "blocked":
imgui.text_colored(imgui.ImVec4(1.0, 0.0, 0.0, 1.0), "BLOCKED")
else:
imgui.text(status)
imgui.table_next_column()
progress = track.get("progress", 0.0)
if progress < 0.33:
p_color = imgui.ImVec4(1.0, 0.0, 0.0, 1.0)
elif progress < 0.66:
p_color = imgui.ImVec4(1.0, 1.0, 0.0, 1.0)
else:
p_color = imgui.ImVec4(0.0, 1.0, 0.0, 1.0)
imgui.push_style_color(imgui.Col_.plot_histogram, p_color)
imgui.progress_bar(progress, imgui.ImVec2(-1, 0), f"{int(progress*100)}%")
imgui.pop_style_color()
imgui.table_next_column()
if imgui.button(f"Load##{track.get('id')}"):
self._cb_load_track(str(track.get("id") or ""))
imgui.end_table()
# 1b. New Track Form
imgui.text("Create New Track")
changed_n, self.ui_new_track_name = imgui.input_text("Name##new_track", self.ui_new_track_name)
changed_d, self.ui_new_track_desc = imgui.input_text_multiline("Description##new_track", self.ui_new_track_desc, imgui.ImVec2(-1, 60))
imgui.text("Type:")
imgui.same_line()
if imgui.begin_combo("##track_type", self.ui_new_track_type):
for ttype in ["feature", "chore", "fix"]:
if imgui.selectable(ttype, self.ui_new_track_type == ttype)[0]:
self.ui_new_track_type = ttype
imgui.end_combo()
if imgui.button("Create Track"):
self._cb_create_track(self.ui_new_track_name, self.ui_new_track_desc, self.ui_new_track_type)
self.ui_new_track_name = ""
self.ui_new_track_desc = ""
self._render_mma_track_browser()
imgui.separator()
# 2. Global Controls
changed, self.mma_step_mode = imgui.checkbox("Step Mode (HITL)", self.mma_step_mode)
if changed:
# We could push an event here if the engine needs to know immediately
pass
imgui.same_line()
imgui.text(f"Status: {self.mma_status.upper()}")
if self.controller and hasattr(self.controller, 'engine') and self.controller.engine and hasattr(self.controller.engine, '_pause_event'):
imgui.same_line()
is_paused = self.controller.engine._pause_event.is_set()
label = "Resume" if is_paused else "Pause"
if imgui.button(label):
if is_paused:
self.controller.engine.resume()
else:
self.controller.engine.pause()
if self.active_tier:
imgui.same_line()
imgui.text_colored(C_VAL, f"| Active: {self.active_tier}")
# Approval pending indicator
any_pending = (
len(self._pending_mma_spawns) > 0 or
len(self._pending_mma_approvals) > 0 or
self._pending_ask_dialog
)
if any_pending:
alpha = abs(math.sin(time.time() * 5))
imgui.same_line()
c = imgui.ImVec4(1.0, 0.3, 0.3, alpha)
if is_nerv: c = vec4(255, 72, 64, alpha) # ALERT_RED
imgui.text_colored(c, " APPROVAL PENDING")
imgui.same_line()
if imgui.button("Go to Approval"):
pass # scroll/focus handled by existing dialog rendering
self._render_mma_global_controls()
imgui.separator()
# 3. Token Usage Table
imgui.text("Tier Usage (Tokens & Cost)")
if imgui.begin_table("mma_usage", 5, imgui.TableFlags_.borders | imgui.TableFlags_.row_bg):
imgui.table_setup_column("Tier")
imgui.table_setup_column("Model")
imgui.table_setup_column("Input")
imgui.table_setup_column("Output")
imgui.table_setup_column("Est. Cost")
imgui.table_headers_row()
usage = self.mma_tier_usage
total_cost = 0.0
for tier, stats in usage.items():
imgui.table_next_row()
imgui.table_next_column()
imgui.text(tier)
imgui.table_next_column()
model = stats.get('model', 'unknown')
imgui.text(model)
imgui.table_next_column()
in_t = stats.get('input', 0)
imgui.text(f"{in_t:,}")
imgui.table_next_column()
out_t = stats.get('output', 0)
imgui.text(f"{out_t:,}")
imgui.table_next_column()
cost = cost_tracker.estimate_cost(model, in_t, out_t)
total_cost += cost
imgui.text(f"${cost:,.4f}")
# Total Row
imgui.table_next_row()
imgui.table_set_bg_color(imgui.TableBgTarget_.row_bg0, imgui.get_color_u32(imgui.Col_.plot_lines_hovered))
imgui.table_next_column()
imgui.text("TOTAL")
imgui.table_next_column()
imgui.text("")
imgui.table_next_column()
imgui.text("")
imgui.table_next_column()
imgui.text("")
imgui.table_next_column()
imgui.text(f"${total_cost:,.4f}")
imgui.end_table()
imgui.separator()
# 3b. Tier Model Config
if imgui.collapsing_header("Tier Model Config"):
for tier in self.mma_tier_usage.keys():
imgui.text(f"{tier}:")
imgui.same_line()
current_model = self.mma_tier_usage[tier].get("model", "unknown")
current_provider = self.mma_tier_usage[tier].get("provider", "gemini")
imgui.push_id(f"tier_cfg_{tier}")
# Provider selection
imgui.push_item_width(80)
if imgui.begin_combo("##prov", current_provider):
for p in models.PROVIDERS:
if imgui.selectable(p, p == current_provider)[0]:
self.mma_tier_usage[tier]["provider"] = p
# Reset model to default for provider
models_list = self.controller.all_available_models.get(p, [])
if models_list:
self.mma_tier_usage[tier]["model"] = models_list[0]
imgui.end_combo()
imgui.pop_item_width()
imgui.same_line()
# Model selection
imgui.push_item_width(150)
models_list = self.controller.all_available_models.get(current_provider, [])
if imgui.begin_combo("##model", current_model):
for model in models_list:
if imgui.selectable(model, current_model == model)[0]:
self.mma_tier_usage[tier]["model"] = model
imgui.end_combo()
imgui.pop_item_width()
imgui.same_line()
# Tool Preset selection
imgui.push_item_width(-1)
current_preset = self.mma_tier_usage[tier].get("tool_preset") or "None"
preset_names = ["None"] + sorted(self.controller.tool_presets.keys())
if imgui.begin_combo("##preset", current_preset):
for preset_name in preset_names:
if imgui.selectable(preset_name, current_preset == preset_name)[0]:
self.mma_tier_usage[tier]["tool_preset"] = None if preset_name == "None" else preset_name
imgui.end_combo()
imgui.pop_item_width()
imgui.same_line()
# Persona selection
imgui.push_item_width(150)
current_persona = self.mma_tier_usage[tier].get("persona") or "None"
personas = getattr(self.controller, 'personas', {})
persona_options = ["None"] + sorted(personas.keys())
if imgui.begin_combo("##persona", current_persona):
for persona_name in persona_options:
if imgui.selectable(persona_name, current_persona == persona_name)[0]:
self.mma_tier_usage[tier]["persona"] = None if persona_name == "None" else persona_name
imgui.end_combo()
imgui.pop_item_width()
imgui.pop_id()
self._render_mma_usage_section()
imgui.separator()
self._render_ticket_queue()
imgui.separator()
ch, self.ui_separate_task_dag = imgui.checkbox("Pop Out Task DAG", self.ui_separate_task_dag)
if ch:
self.show_windows["Task DAG"] = self.ui_separate_task_dag
if not self.ui_separate_task_dag:
self._render_task_dag_panel()
# 6. Edit Selected Ticket
if self.ui_selected_ticket_id:
imgui.separator()
imgui.text_colored(C_VAL, f"Editing: {self.ui_selected_ticket_id}")
ticket = next((t for t in self.active_tickets if str(t.get('id', '')) == self.ui_selected_ticket_id), None)
if ticket:
imgui.text(f"Status: {ticket.get('status', 'todo')}")
prio = ticket.get('priority', 'medium')
imgui.text("Priority:")
imgui.same_line()
if imgui.begin_combo(f"##edit_prio_{ticket.get('id')}", prio):
for p_opt in ['high', 'medium', 'low']:
if imgui.selectable(p_opt, p_opt == prio)[0]:
ticket['priority'] = p_opt
self._push_mma_state_update()
imgui.end_combo()
imgui.text(f"Target: {ticket.get('target_file', '')}")
deps = ticket.get('depends_on', [])
imgui.text(f"Depends on: {', '.join(deps)}")
personas = getattr(self.controller, 'personas', {})
current_persona = ticket.get('persona_id', '')
imgui.text("Persona Override:")
imgui.same_line()
persona_options = ["None"] + sorted(personas.keys())
current_idx = persona_options.index(current_persona) + 1 if current_persona in persona_options else 0
_, current_idx = imgui.combo(f"##ticket_persona_{ticket.get('id')}", current_idx, persona_options)
if current_idx > 0:
ticket['persona_id'] = None if persona_options[current_idx] == "None" else persona_options[current_idx]
else:
ticket['persona_id'] = ""
if imgui.button(f"Mark Complete##{self.ui_selected_ticket_id}"):
ticket['status'] = 'done'
self._push_mma_state_update()
imgui.same_line()
if imgui.button(f"Delete##{self.ui_selected_ticket_id}"):
self.active_tickets = [t for t in self.active_tickets if str(t.get('id', '')) != self.ui_selected_ticket_id]
self.ui_selected_ticket_id = None
self._push_mma_state_update()
self._render_window_if_open("Task DAG", self._render_task_dag_panel, not self.ui_separate_task_dag)
if self.ui_selected_ticket_id: self._render_mma_ticket_editor()
imgui.separator()
imgui.text("Agent Streams")
if imgui.begin_tab_bar("mma_streams_tabs"):
# Tier 1
if imgui.begin_tab_item("Tier 1")[0]:
ch, self.ui_separate_tier1 = imgui.checkbox("Pop Out Tier 1", self.ui_separate_tier1)
if ch: self.show_windows["Tier 1: Strategy"] = self.ui_separate_tier1
if not self.ui_separate_tier1:
self._render_tier_stream_panel("Tier 1", "Tier 1")
else:
imgui.text_disabled("Tier 1 stream is detached.")
imgui.end_tab_item()
# Tier 2
if imgui.begin_tab_item("Tier 2")[0]:
ch, self.ui_separate_tier2 = imgui.checkbox("Pop Out Tier 2", self.ui_separate_tier2)
if ch: self.show_windows["Tier 2: Tech Lead"] = self.ui_separate_tier2
if not self.ui_separate_tier2:
self._render_tier_stream_panel("Tier 2", "Tier 2 (Tech Lead)")
else:
imgui.text_disabled("Tier 2 stream is detached.")
imgui.end_tab_item()
# Tier 3
if imgui.begin_tab_item("Tier 3")[0]:
ch, self.ui_separate_tier3 = imgui.checkbox("Pop Out Tier 3", self.ui_separate_tier3)
if ch: self.show_windows["Tier 3: Workers"] = self.ui_separate_tier3
if not self.ui_separate_tier3:
self._render_tier_stream_panel("Tier 3", None)
else:
imgui.text_disabled("Tier 3 stream is detached.")
imgui.end_tab_item()
# Tier 4
if imgui.begin_tab_item("Tier 4")[0]:
ch, self.ui_separate_tier4 = imgui.checkbox("Pop Out Tier 4", self.ui_separate_tier4)
if ch: self.show_windows["Tier 4: QA"] = self.ui_separate_tier4
if not self.ui_separate_tier4:
self._render_tier_stream_panel("Tier 4", "Tier 4 (QA)")
else:
imgui.text_disabled("Tier 4 stream is detached.")
imgui.end_tab_item()
if getattr(self, "ui_project_execution_mode", "native") == "beads":
if imgui.begin_tab_item("Beads")[0]:
self._render_beads_tab()
imgui.end_tab_item()
imgui.end_tab_bar()
self._render_mma_agent_streams()
if self.perf_profiling_enabled: self.perf_monitor.end_component("_render_mma_dashboard")
def _render_task_dag_panel(self) -> None:
# 4. Task DAG Visualizer