refactor(controller): Replace legacy _set_status calls with direct property assignment
This commit is contained in:
+49
-56
@@ -671,13 +671,7 @@ class AppController:
|
|||||||
else:
|
else:
|
||||||
ai_client._gemini_cli_adapter.binary_path = str(path)
|
ai_client._gemini_cli_adapter.binary_path = str(path)
|
||||||
|
|
||||||
def _set_status(self, status: str) -> None:
|
|
||||||
"""Thread-safe update of ai_status via the GUI task queue."""
|
|
||||||
self.ai_status = status
|
|
||||||
|
|
||||||
def _set_mma_status(self, status: str) -> None:
|
|
||||||
"""Thread-safe update of mma_status via the GUI task queue."""
|
|
||||||
self.mma_status = status
|
|
||||||
|
|
||||||
def _set_rag_status(self, status: str) -> None:
|
def _set_rag_status(self, status: str) -> None:
|
||||||
"""Thread-safe update of rag_status via the GUI task queue."""
|
"""Thread-safe update of rag_status via the GUI task queue."""
|
||||||
@@ -1236,7 +1230,7 @@ class AppController:
|
|||||||
session_dir = log_path.parent
|
session_dir = log_path.parent
|
||||||
|
|
||||||
if not log_file.exists():
|
if not log_file.exists():
|
||||||
self._set_status(f"log file not found: {log_file}")
|
self.ai_status = f"log file not found: {log_file}"
|
||||||
return
|
return
|
||||||
|
|
||||||
def _resolve_log_ref(content: Any, session_dir: Path) -> str:
|
def _resolve_log_ref(content: Any, session_dir: Path) -> str:
|
||||||
@@ -1376,7 +1370,7 @@ class AppController:
|
|||||||
except json.JSONDecodeError:
|
except json.JSONDecodeError:
|
||||||
continue
|
continue
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
self._set_status(f"log load error: {e}")
|
self.ai_status = f"log load error: {e}"
|
||||||
return
|
return
|
||||||
|
|
||||||
self.session_usage = new_usage
|
self.session_usage = new_usage
|
||||||
@@ -1395,7 +1389,7 @@ class AppController:
|
|||||||
self.prior_tool_calls = final_tool_calls
|
self.prior_tool_calls = final_tool_calls
|
||||||
self.is_viewing_prior_session = True
|
self.is_viewing_prior_session = True
|
||||||
self._trigger_gui_refresh()
|
self._trigger_gui_refresh()
|
||||||
self._set_status(f"viewing prior session: {session_dir.name} ({len(entries)} entries)")
|
self.ai_status = f"viewing prior session: {session_dir.name} ({len(entries)} entries)"
|
||||||
|
|
||||||
|
|
||||||
def cb_exit_prior_session(self):
|
def cb_exit_prior_session(self):
|
||||||
@@ -1418,11 +1412,11 @@ class AppController:
|
|||||||
self.prior_disc_entries.clear()
|
self.prior_disc_entries.clear()
|
||||||
self.prior_tool_calls.clear()
|
self.prior_tool_calls.clear()
|
||||||
self._trigger_gui_refresh()
|
self._trigger_gui_refresh()
|
||||||
self._set_status('idle')
|
self.ai_status = 'idle'
|
||||||
|
|
||||||
def cb_prune_logs(self) -> None:
|
def cb_prune_logs(self) -> None:
|
||||||
"""Manually triggers the log pruning process with aggressive thresholds."""
|
"""Manually triggers the log pruning process with aggressive thresholds."""
|
||||||
self._set_status("Manual prune started (Age > 0d, Size < 100KB)...")
|
self.ai_status = "Manual prune started (Age > 0d, Size < 100KB)..."
|
||||||
|
|
||||||
def run_manual_prune() -> None:
|
def run_manual_prune() -> None:
|
||||||
try:
|
try:
|
||||||
@@ -1433,9 +1427,9 @@ class AppController:
|
|||||||
# Aggressive: Prune anything not whitelisted, even if just created, if under 100KB
|
# Aggressive: Prune anything not whitelisted, even if just created, if under 100KB
|
||||||
# Note: max_age_days=0 means cutoff is NOW.
|
# Note: max_age_days=0 means cutoff is NOW.
|
||||||
pruner.prune(max_age_days=0, min_size_kb=100)
|
pruner.prune(max_age_days=0, min_size_kb=100)
|
||||||
self._set_status("Manual prune complete.")
|
self.ai_status = "Manual prune complete."
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
self._set_status(f"Manual prune error: {e}")
|
self.ai_status = f"Manual prune error: {e}"
|
||||||
print(f"Error during manual log pruning: {e}")
|
print(f"Error during manual log pruning: {e}")
|
||||||
|
|
||||||
thread = threading.Thread(target=run_manual_prune, daemon=True)
|
thread = threading.Thread(target=run_manual_prune, daemon=True)
|
||||||
@@ -1481,7 +1475,7 @@ class AppController:
|
|||||||
thread.start()
|
thread.start()
|
||||||
|
|
||||||
def _fetch_models(self, provider: str) -> None:
|
def _fetch_models(self, provider: str) -> None:
|
||||||
self._set_status("fetching models...")
|
self.ai_status = "fetching models..."
|
||||||
|
|
||||||
def do_fetch() -> None:
|
def do_fetch() -> None:
|
||||||
try:
|
try:
|
||||||
@@ -1497,9 +1491,9 @@ class AppController:
|
|||||||
if self.current_model not in models_list and models_list:
|
if self.current_model not in models_list and models_list:
|
||||||
self.current_model = models_list[0]
|
self.current_model = models_list[0]
|
||||||
ai_client.set_provider(self._current_provider, self.current_model)
|
ai_client.set_provider(self._current_provider, self.current_model)
|
||||||
self._set_status(f"models loaded: {len(models_list)}")
|
self.ai_status = f"models loaded: {len(models_list)}"
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
self._set_status(f"model fetch error: {e}")
|
self.ai_status = f"model fetch error: {e}"
|
||||||
self.models_thread = threading.Thread(target=do_fetch, daemon=True)
|
self.models_thread = threading.Thread(target=do_fetch, daemon=True)
|
||||||
self.models_thread.start()
|
self.models_thread.start()
|
||||||
|
|
||||||
@@ -1611,7 +1605,7 @@ class AppController:
|
|||||||
|
|
||||||
def _handle_request_event(self, event: events.UserRequestEvent) -> None:
|
def _handle_request_event(self, event: events.UserRequestEvent) -> None:
|
||||||
"""Processes a UserRequestEvent by calling the AI client."""
|
"""Processes a UserRequestEvent by calling the AI client."""
|
||||||
self._set_status('sending...')
|
self.ai_status = 'sending...'
|
||||||
ai_client.set_current_tier(None) # Ensure main discussion is untagged
|
ai_client.set_current_tier(None) # Ensure main discussion is untagged
|
||||||
# Clear response area for new turn
|
# Clear response area for new turn
|
||||||
self.ai_response = ""
|
self.ai_response = ""
|
||||||
@@ -1785,9 +1779,9 @@ class AppController:
|
|||||||
|
|
||||||
def _confirm_and_run(self, script: str, base_dir: str, qa_callback: Optional[Callable[[str], str]] = None, patch_callback: Optional[Callable[[str, str], Optional[str]]] = None) -> Optional[str]:
|
def _confirm_and_run(self, script: str, base_dir: str, qa_callback: Optional[Callable[[str], str]] = None, patch_callback: Optional[Callable[[str, str], Optional[str]]] = None) -> Optional[str]:
|
||||||
if self.test_hooks_enabled and not getattr(self, "ui_manual_approve", False):
|
if self.test_hooks_enabled and not getattr(self, "ui_manual_approve", False):
|
||||||
self._set_status("running powershell...")
|
self.ai_status = "running powershell..."
|
||||||
output = shell_runner.run_powershell(script, base_dir, qa_callback=qa_callback, patch_callback=patch_callback)
|
output = shell_runner.run_powershell(script, base_dir, qa_callback=qa_callback, patch_callback=patch_callback)
|
||||||
self._set_status("powershell done, awaiting AI...")
|
self.ai_status = "powershell done, awaiting AI..."
|
||||||
return output
|
return output
|
||||||
dialog = ConfirmDialog(script, base_dir)
|
dialog = ConfirmDialog(script, base_dir)
|
||||||
is_headless = "--headless" in sys.argv
|
is_headless = "--headless" in sys.argv
|
||||||
@@ -1814,10 +1808,10 @@ class AppController:
|
|||||||
if not approved:
|
if not approved:
|
||||||
self._append_tool_log(final_script, "REJECTED by user")
|
self._append_tool_log(final_script, "REJECTED by user")
|
||||||
return None
|
return None
|
||||||
self._set_status("running powershell...")
|
self.ai_status = "running powershell..."
|
||||||
output = shell_runner.run_powershell(final_script, base_dir, qa_callback=qa_callback, patch_callback=patch_callback)
|
output = shell_runner.run_powershell(final_script, base_dir, qa_callback=qa_callback, patch_callback=patch_callback)
|
||||||
self._append_tool_log(final_script, output)
|
self._append_tool_log(final_script, output)
|
||||||
self._set_status("powershell done, awaiting AI...")
|
self.ai_status = "powershell done, awaiting AI..."
|
||||||
return output
|
return output
|
||||||
|
|
||||||
def _append_tool_log(self, script: str, result: str, source_tier: str | None = None, elapsed_ms: float = 0.0) -> None:
|
def _append_tool_log(self, script: str, result: str, source_tier: str | None = None, elapsed_ms: float = 0.0) -> None:
|
||||||
@@ -2165,7 +2159,7 @@ class AppController:
|
|||||||
self._flush_to_project()
|
self._flush_to_project()
|
||||||
self._flush_to_config()
|
self._flush_to_config()
|
||||||
models.save_config(self.config)
|
models.save_config(self.config)
|
||||||
self._set_status("config saved")
|
self.ai_status = "config saved"
|
||||||
|
|
||||||
def _cb_reset_base_prompt(self, user_data=None) -> None:
|
def _cb_reset_base_prompt(self, user_data=None) -> None:
|
||||||
self.ui_base_system_prompt = ai_client._SYSTEM_PROMPT
|
self.ui_base_system_prompt = ai_client._SYSTEM_PROMPT
|
||||||
@@ -2187,7 +2181,7 @@ class AppController:
|
|||||||
|
|
||||||
def _switch_project(self, path: str) -> None:
|
def _switch_project(self, path: str) -> None:
|
||||||
if not Path(path).exists():
|
if not Path(path).exists():
|
||||||
self._set_status(f"project file not found: {path}")
|
self.ai_status = f"project file not found: {path}"
|
||||||
return
|
return
|
||||||
self._flush_to_project()
|
self._flush_to_project()
|
||||||
try:
|
try:
|
||||||
@@ -2199,10 +2193,10 @@ class AppController:
|
|||||||
from src.personas import PersonaManager
|
from src.personas import PersonaManager
|
||||||
self.persona_manager = PersonaManager(new_root)
|
self.persona_manager = PersonaManager(new_root)
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
self._set_status(f"failed to load project: {e}")
|
self.ai_status = f"failed to load project: {e}"
|
||||||
return
|
return
|
||||||
self._refresh_from_project()
|
self._refresh_from_project()
|
||||||
self._set_status(f"switched to: {Path(path).stem}")
|
self.ai_status = f"switched to: {Path(path).stem}"
|
||||||
|
|
||||||
def _refresh_from_project(self) -> None:
|
def _refresh_from_project(self) -> None:
|
||||||
# Deserialize FileItems in files.paths
|
# Deserialize FileItems in files.paths
|
||||||
@@ -2391,9 +2385,9 @@ class AppController:
|
|||||||
else:
|
else:
|
||||||
self.disc_entries = []
|
self.disc_entries = []
|
||||||
self._recalculate_session_usage()
|
self._recalculate_session_usage()
|
||||||
self._set_status(f"Loaded track: {state.metadata.name}")
|
self.ai_status = f"Loaded track: {state.metadata.name}"
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
self._set_status(f"Load track error: {e}")
|
self.ai_status = f"Load track error: {e}"
|
||||||
print(f"Error loading track {track_id}: {e}")
|
print(f"Error loading track {track_id}: {e}")
|
||||||
|
|
||||||
def _save_active_project(self) -> None:
|
def _save_active_project(self) -> None:
|
||||||
@@ -2402,7 +2396,7 @@ class AppController:
|
|||||||
cleaned = project_manager.clean_nones(self.project)
|
cleaned = project_manager.clean_nones(self.project)
|
||||||
project_manager.save_project(cleaned, self.active_project_path)
|
project_manager.save_project(cleaned, self.active_project_path)
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
self._set_status(f"save error: {e}")
|
self.ai_status = f"save error: {e}"
|
||||||
|
|
||||||
def _get_discussion_names(self) -> list[str]:
|
def _get_discussion_names(self) -> list[str]:
|
||||||
disc_sec = self.project.get("discussion", {})
|
disc_sec = self.project.get("discussion", {})
|
||||||
@@ -2414,7 +2408,7 @@ class AppController:
|
|||||||
disc_sec = self.project.get("discussion", {})
|
disc_sec = self.project.get("discussion", {})
|
||||||
discussions = disc_sec.get("discussions", {})
|
discussions = disc_sec.get("discussions", {})
|
||||||
if name not in discussions:
|
if name not in discussions:
|
||||||
self._set_status(f"discussion not found: {name}")
|
self.ai_status = f"discussion not found: {name}"
|
||||||
return
|
return
|
||||||
self.active_discussion = name
|
self.active_discussion = name
|
||||||
self._track_discussion_active = False
|
self._track_discussion_active = False
|
||||||
@@ -2422,7 +2416,7 @@ class AppController:
|
|||||||
disc_data = discussions[name]
|
disc_data = discussions[name]
|
||||||
with self._disc_entries_lock:
|
with self._disc_entries_lock:
|
||||||
self.disc_entries = models.parse_history_entries(disc_data.get("history", []), self.disc_roles)
|
self.disc_entries = models.parse_history_entries(disc_data.get("history", []), self.disc_roles)
|
||||||
self._set_status(f"discussion: {name}")
|
self.ai_status = f"discussion: {name}"
|
||||||
|
|
||||||
def _flush_disc_entries_to_project(self) -> None:
|
def _flush_disc_entries_to_project(self) -> None:
|
||||||
history_strings = [project_manager.entry_to_str(e) for e in self.disc_entries]
|
history_strings = [project_manager.entry_to_str(e) for e in self.disc_entries]
|
||||||
@@ -2439,7 +2433,7 @@ class AppController:
|
|||||||
disc_sec = self.project.setdefault("discussion", {})
|
disc_sec = self.project.setdefault("discussion", {})
|
||||||
discussions = disc_sec.setdefault("discussions", {})
|
discussions = disc_sec.setdefault("discussions", {})
|
||||||
if name in discussions:
|
if name in discussions:
|
||||||
self._set_status(f"discussion '{name}' already exists")
|
self.ai_status = f"discussion '{name}' already exists"
|
||||||
return
|
return
|
||||||
discussions[name] = project_manager.default_discussion()
|
discussions[name] = project_manager.default_discussion()
|
||||||
self._switch_discussion(name)
|
self._switch_discussion(name)
|
||||||
@@ -2464,7 +2458,7 @@ class AppController:
|
|||||||
if old_name not in discussions:
|
if old_name not in discussions:
|
||||||
return
|
return
|
||||||
if new_name in discussions:
|
if new_name in discussions:
|
||||||
self._set_status(f"discussion '{new_name}' already exists")
|
self.ai_status = f"discussion '{new_name}' already exists"
|
||||||
return
|
return
|
||||||
discussions[new_name] = discussions.pop(old_name)
|
discussions[new_name] = discussions.pop(old_name)
|
||||||
if self.active_discussion == old_name:
|
if self.active_discussion == old_name:
|
||||||
@@ -2475,7 +2469,7 @@ class AppController:
|
|||||||
disc_sec = self.project.get("discussion", {})
|
disc_sec = self.project.get("discussion", {})
|
||||||
discussions = disc_sec.get("discussions", {})
|
discussions = disc_sec.get("discussions", {})
|
||||||
if len(discussions) <= 1:
|
if len(discussions) <= 1:
|
||||||
self._set_status("cannot delete the last discussion")
|
self.ai_status = "cannot delete the last discussion"
|
||||||
return
|
return
|
||||||
if name not in discussions:
|
if name not in discussions:
|
||||||
return
|
return
|
||||||
@@ -2558,7 +2552,7 @@ class AppController:
|
|||||||
discussions = disc_sec.get("discussions", {})
|
discussions = disc_sec.get("discussions", {})
|
||||||
for d_name in discussions:
|
for d_name in discussions:
|
||||||
discussions[d_name]["history"] = []
|
discussions[d_name]["history"] = []
|
||||||
self._set_status("session reset")
|
self.ai_status = "session reset"
|
||||||
self.ai_response = ""
|
self.ai_response = ""
|
||||||
self.ui_ai_input = ""
|
self.ui_ai_input = ""
|
||||||
self.ui_manual_approve = False
|
self.ui_manual_approve = False
|
||||||
@@ -2581,11 +2575,11 @@ class AppController:
|
|||||||
md, path, *_ = self._do_generate()
|
md, path, *_ = self._do_generate()
|
||||||
self.last_md = md
|
self.last_md = md
|
||||||
self.last_md_path = path
|
self.last_md_path = path
|
||||||
self._set_status(f"md written: {path.name}")
|
self.ai_status = f"md written: {path.name}"
|
||||||
# Refresh token budget metrics with CURRENT md
|
# Refresh token budget metrics with CURRENT md
|
||||||
self._refresh_api_metrics({}, md_content=md)
|
self._refresh_api_metrics({}, md_content=md)
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
self._set_status(f"error: {e}")
|
self.ai_status = f"error: {e}"
|
||||||
threading.Thread(target=worker, daemon=True).start()
|
threading.Thread(target=worker, daemon=True).start()
|
||||||
|
|
||||||
def _handle_generate_send(self) -> None:
|
def _handle_generate_send(self) -> None:
|
||||||
@@ -2600,7 +2594,7 @@ class AppController:
|
|||||||
self.last_md = md
|
self.last_md = md
|
||||||
self.last_md_path = path
|
self.last_md_path = path
|
||||||
self.last_file_items = file_items
|
self.last_file_items = file_items
|
||||||
self._set_status("sending...")
|
self.ai_status = "sending..."
|
||||||
user_msg = self.ui_ai_input
|
user_msg = self.ui_ai_input
|
||||||
|
|
||||||
# RAG Retrieval
|
# RAG Retrieval
|
||||||
@@ -2639,7 +2633,7 @@ class AppController:
|
|||||||
except Exception as e:
|
except Exception as e:
|
||||||
sys.stderr.write(f"[DEBUG] _do_generate ERROR: {e}\n{traceback.format_exc()}\n")
|
sys.stderr.write(f"[DEBUG] _do_generate ERROR: {e}\n{traceback.format_exc()}\n")
|
||||||
sys.stderr.flush()
|
sys.stderr.flush()
|
||||||
self._set_status(f"generate error: {e}")
|
self.ai_status = f"generate error: {e}"
|
||||||
threading.Thread(target=worker, daemon=True).start()
|
threading.Thread(target=worker, daemon=True).start()
|
||||||
|
|
||||||
def _recalculate_session_usage(self) -> None:
|
def _recalculate_session_usage(self) -> None:
|
||||||
@@ -2819,7 +2813,7 @@ class AppController:
|
|||||||
sys.stderr.write("[DEBUG] _cb_plan_epic _bg_task started\n")
|
sys.stderr.write("[DEBUG] _cb_plan_epic _bg_task started\n")
|
||||||
sys.stderr.flush()
|
sys.stderr.flush()
|
||||||
try:
|
try:
|
||||||
self._set_status("Planning Epic (Tier 1)...")
|
self.ai_status = "Planning Epic (Tier 1)..."
|
||||||
history = orchestrator_pm.get_track_history_summary()
|
history = orchestrator_pm.get_track_history_summary()
|
||||||
sys.stderr.write(f"[DEBUG] History summary length: {len(history)}\n")
|
sys.stderr.write(f"[DEBUG] History summary length: {len(history)}\n")
|
||||||
sys.stderr.flush()
|
sys.stderr.flush()
|
||||||
@@ -2856,7 +2850,7 @@ class AppController:
|
|||||||
"payload": tracks
|
"payload": tracks
|
||||||
})
|
})
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
self._set_status(f"Epic plan error: {e}")
|
self.ai_status = f"Epic plan error: {e}"
|
||||||
print(f"ERROR in _cb_plan_epic background task: {e}")
|
print(f"ERROR in _cb_plan_epic background task: {e}")
|
||||||
threading.Thread(target=_bg_task, daemon=True).start()
|
threading.Thread(target=_bg_task, daemon=True).start()
|
||||||
|
|
||||||
@@ -2866,7 +2860,7 @@ class AppController:
|
|||||||
def _bg_task() -> None:
|
def _bg_task() -> None:
|
||||||
sys.stderr.write("[DEBUG] _cb_accept_tracks _bg_task started\n")
|
sys.stderr.write("[DEBUG] _cb_accept_tracks _bg_task started\n")
|
||||||
# Generate skeletons once
|
# Generate skeletons once
|
||||||
self._set_status("Phase 2: Generating skeletons for all tracks...")
|
self.ai_status = "Phase 2: Generating skeletons for all tracks..."
|
||||||
sys.stderr.write("[DEBUG] Creating ASTParser...\n")
|
sys.stderr.write("[DEBUG] Creating ASTParser...\n")
|
||||||
parser = ASTParser(language="python")
|
parser = ASTParser(language="python")
|
||||||
generated_skeletons = ""
|
generated_skeletons = ""
|
||||||
@@ -2876,7 +2870,7 @@ class AppController:
|
|||||||
sys.stderr.write(f"[DEBUG] Scanning {len(files_to_scan)} files for skeletons...\n")
|
sys.stderr.write(f"[DEBUG] Scanning {len(files_to_scan)} files for skeletons...\n")
|
||||||
for i, file_path in enumerate(files_to_scan):
|
for i, file_path in enumerate(files_to_scan):
|
||||||
try:
|
try:
|
||||||
self._set_status(f"Phase 2: Scanning files ({i+1}/{len(files_to_scan)})...")
|
self.ai_status = f"Phase 2: Scanning files ({i+1}/{len(files_to_scan)})..."
|
||||||
abs_path = Path(self.active_project_root) / file_path
|
abs_path = Path(self.active_project_root) / file_path
|
||||||
if abs_path.exists() and abs_path.suffix == ".py":
|
if abs_path.exists() and abs_path.suffix == ".py":
|
||||||
with open(abs_path, "r", encoding="utf-8") as f:
|
with open(abs_path, "r", encoding="utf-8") as f:
|
||||||
@@ -2886,19 +2880,19 @@ class AppController:
|
|||||||
sys.stderr.write(f"[DEBUG] Error parsing skeleton for {file_path}: {e}\n")
|
sys.stderr.write(f"[DEBUG] Error parsing skeleton for {file_path}: {e}\n")
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
sys.stderr.write(f"[DEBUG] Error in scan loop: {e}\n")
|
sys.stderr.write(f"[DEBUG] Error in scan loop: {e}\n")
|
||||||
self._set_status(f"Error generating skeletons: {e}")
|
self.ai_status = f"Error generating skeletons: {e}"
|
||||||
return # Exit if skeleton generation fails
|
return # Exit if skeleton generation fails
|
||||||
sys.stderr.write("[DEBUG] Skeleton generation complete. Starting tracks...\n")
|
sys.stderr.write("[DEBUG] Skeleton generation complete. Starting tracks...\n")
|
||||||
# Now loop through tracks and call _start_track_logic with generated skeletons
|
# Now loop through tracks and call _start_track_logic with generated skeletons
|
||||||
total_tracks = len(self.proposed_tracks)
|
total_tracks = len(self.proposed_tracks)
|
||||||
for i, track_data in enumerate(self.proposed_tracks):
|
for i, track_data in enumerate(self.proposed_tracks):
|
||||||
title = track_data.get("title") or track_data.get("goal", "Untitled Track")
|
title = track_data.get("title") or track_data.get("goal", "Untitled Track")
|
||||||
self._set_status(f"Processing track {i+1} of {total_tracks}: '{title}'...")
|
self.ai_status = f"Processing track {i+1} of {total_tracks}: '{title}'..."
|
||||||
self._start_track_logic(track_data, skeletons_str=generated_skeletons) # Pass skeletons
|
self._start_track_logic(track_data, skeletons_str=generated_skeletons) # Pass skeletons
|
||||||
sys.stderr.write("[DEBUG] All tracks started. Refreshing...\n")
|
sys.stderr.write("[DEBUG] All tracks started. Refreshing...\n")
|
||||||
with self._pending_gui_tasks_lock:
|
with self._pending_gui_tasks_lock:
|
||||||
self._pending_gui_tasks.append({'action': 'refresh_from_project'}) # Ensure UI refresh after tracks are started
|
self._pending_gui_tasks.append({'action': 'refresh_from_project'}) # Ensure UI refresh after tracks are started
|
||||||
self._set_status(f"All {total_tracks} tracks accepted and execution started.")
|
self.ai_status = f"All {total_tracks} tracks accepted and execution started."
|
||||||
threading.Thread(target=_bg_task, daemon=True).start()
|
threading.Thread(target=_bg_task, daemon=True).start()
|
||||||
|
|
||||||
def _cb_start_track(self, user_data: Any = None) -> None:
|
def _cb_start_track(self, user_data: Any = None) -> None:
|
||||||
@@ -2911,25 +2905,25 @@ class AppController:
|
|||||||
if self.active_track and self.active_track.id == track_id:
|
if self.active_track and self.active_track.id == track_id:
|
||||||
# Use the active track object directly to start execution
|
# Use the active track object directly to start execution
|
||||||
print(f"[DEBUG] _cb_start_track: track_id={self.active_track.id}, desc={self.active_track.description}")
|
print(f"[DEBUG] _cb_start_track: track_id={self.active_track.id}, desc={self.active_track.description}")
|
||||||
self._set_mma_status("running")
|
self.mma_status = "running"
|
||||||
engine = multi_agent_conductor.ConductorEngine(self.active_track, self.event_queue, auto_queue=not self.mma_step_mode)
|
engine = multi_agent_conductor.ConductorEngine(self.active_track, self.event_queue, auto_queue=not self.mma_step_mode)
|
||||||
self.engines[self.active_track.id] = engine
|
self.engines[self.active_track.id] = engine
|
||||||
flat = project_manager.flat_config(self.project, self.active_discussion, track_id=self.active_track.id)
|
flat = project_manager.flat_config(self.project, self.active_discussion, track_id=self.active_track.id)
|
||||||
full_md, _, _ = aggregate.run(flat)
|
full_md, _, _ = aggregate.run(flat)
|
||||||
threading.Thread(target=engine.run, kwargs={"md_content": full_md}, daemon=True).start()
|
threading.Thread(target=engine.run, kwargs={"md_content": full_md}, daemon=True).start()
|
||||||
self._set_status(f"Track '{self.active_track.description}' started.")
|
self.ai_status = f"Track '{self.active_track.description}' started."
|
||||||
elif self.active_track and self.active_track.id != track_id:
|
elif self.active_track and self.active_track.id != track_id:
|
||||||
# load_track failed but active_track is still wrong - reload explicitly
|
# load_track failed but active_track is still wrong - reload explicitly
|
||||||
print(f"[DEBUG] _cb_start_track: load failed, trying reload track_id={track_id}")
|
print(f"[DEBUG] _cb_start_track: load failed, trying reload track_id={track_id}")
|
||||||
self._cb_load_track(track_id)
|
self._cb_load_track(track_id)
|
||||||
if self.active_track and self.active_track.id == track_id:
|
if self.active_track and self.active_track.id == track_id:
|
||||||
self._set_mma_status("running")
|
self.mma_status = "running"
|
||||||
engine = multi_agent_conductor.ConductorEngine(self.active_track, self.event_queue, auto_queue=not self.mma_step_mode)
|
engine = multi_agent_conductor.ConductorEngine(self.active_track, self.event_queue, auto_queue=not self.mma_step_mode)
|
||||||
self.engines[self.active_track.id] = engine
|
self.engines[self.active_track.id] = engine
|
||||||
flat = project_manager.flat_config(self.project, self.active_discussion, track_id=self.active_track.id)
|
flat = project_manager.flat_config(self.project, self.active_discussion, track_id=self.active_track.id)
|
||||||
full_md, _, _ = aggregate.run(flat)
|
full_md, _, _ = aggregate.run(flat)
|
||||||
threading.Thread(target=engine.run, kwargs={"md_content": full_md}, daemon=True).start()
|
threading.Thread(target=engine.run, kwargs={"md_content": full_md}, daemon=True).start()
|
||||||
self._set_status(f"Track '{self.active_track.description}' started.")
|
self.ai_status = f"Track '{self.active_track.description}' started."
|
||||||
return
|
return
|
||||||
idx = 0
|
idx = 0
|
||||||
if isinstance(user_data, int):
|
if isinstance(user_data, int):
|
||||||
@@ -2940,15 +2934,15 @@ class AppController:
|
|||||||
track_data = self.proposed_tracks[idx]
|
track_data = self.proposed_tracks[idx]
|
||||||
title = track_data.get("title") or track_data.get("goal", "Untitled Track")
|
title = track_data.get("title") or track_data.get("goal", "Untitled Track")
|
||||||
threading.Thread(target=lambda: self._start_track_logic(track_data), daemon=True).start()
|
threading.Thread(target=lambda: self._start_track_logic(track_data), daemon=True).start()
|
||||||
self._set_status(f"Track '{title}' started.")
|
self.ai_status = f"Track '{title}' started."
|
||||||
|
|
||||||
def _start_track_logic(self, track_data: dict[str, Any], skeletons_str: str | None = None) -> None:
|
def _start_track_logic(self, track_data: dict[str, Any], skeletons_str: str | None = None) -> None:
|
||||||
try:
|
try:
|
||||||
goal = track_data.get("goal", "")
|
goal = track_data.get("goal", "")
|
||||||
title = track_data.get("title") or track_data.get("goal", "Untitled Track")
|
title = track_data.get("title") or track_data.get("goal", "Untitled Track")
|
||||||
self._set_status(f"Phase 2: Generating tickets for {title}...")
|
self.ai_status = f"Phase 2: Generating tickets for {title}..."
|
||||||
skeletons = skeletons_str or "" # Use provided skeletons or empty
|
skeletons = skeletons_str or "" # Use provided skeletons or empty
|
||||||
self._set_status("Phase 2: Calling Tech Lead...")
|
self.ai_status = "Phase 2: Calling Tech Lead..."
|
||||||
_t2_baseline = len(ai_client.get_comms_log())
|
_t2_baseline = len(ai_client.get_comms_log())
|
||||||
raw_tickets = conductor_tech_lead.generate_tickets(goal, skeletons)
|
raw_tickets = conductor_tech_lead.generate_tickets(goal, skeletons)
|
||||||
_t2_new = ai_client.get_comms_log()[_t2_baseline:]
|
_t2_new = ai_client.get_comms_log()[_t2_baseline:]
|
||||||
@@ -2966,10 +2960,10 @@ class AppController:
|
|||||||
"args": [_t2_in, _t2_out]
|
"args": [_t2_in, _t2_out]
|
||||||
})
|
})
|
||||||
if not raw_tickets:
|
if not raw_tickets:
|
||||||
self._set_status(f"Error: No tickets generated for track: {title}")
|
self.ai_status = f"Error: No tickets generated for track: {title}"
|
||||||
print(f"Warning: No tickets generated for track: {title}")
|
print(f"Warning: No tickets generated for track: {title}")
|
||||||
return
|
return
|
||||||
self._set_status("Phase 2: Sorting tickets...")
|
self.ai_status = "Phase 2: Sorting tickets..."
|
||||||
try:
|
try:
|
||||||
sorted_tickets_data = conductor_tech_lead.topological_sort(raw_tickets)
|
sorted_tickets_data = conductor_tech_lead.topological_sort(raw_tickets)
|
||||||
except ValueError as e:
|
except ValueError as e:
|
||||||
@@ -3007,7 +3001,7 @@ class AppController:
|
|||||||
# Start the engine in a separate thread
|
# Start the engine in a separate thread
|
||||||
threading.Thread(target=engine.run, kwargs={"md_content": full_md}, daemon=True).start()
|
threading.Thread(target=engine.run, kwargs={"md_content": full_md}, daemon=True).start()
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
self._set_status(f"Track start error: {e}")
|
self.ai_status = f"Track start error: {e}"
|
||||||
print(f"ERROR in _start_track_logic: {e}")
|
print(f"ERROR in _start_track_logic: {e}")
|
||||||
|
|
||||||
def _cb_ticket_retry(self, ticket_id: str) -> None:
|
def _cb_ticket_retry(self, ticket_id: str) -> None:
|
||||||
@@ -3198,4 +3192,3 @@ class AppController:
|
|||||||
else:
|
else:
|
||||||
self.active_tickets = []
|
self.active_tickets = []
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user