cruft cleanup part 3
This commit is contained in:
+13
-221
@@ -90,9 +90,6 @@ class ConfirmDialog:
|
||||
self._approved = False
|
||||
|
||||
def wait(self) -> tuple[bool, str]:
|
||||
"""
|
||||
[C: src/mcp_client.py:StdioMCPServer.stop, src/multi_agent_conductor.py:confirm_execution, src/multi_agent_conductor.py:confirm_spawn, tests/conftest.py:live_gui, tests/test_ai_client_concurrency.py:run_t1, tests/test_ai_client_concurrency.py:run_t2, tests/test_ai_server.py:test_server_handles_list_models, tests/test_ai_server.py:test_server_handles_unknown_method, tests/test_ai_server.py:test_server_loads_google_genai_quickly, tests/test_ai_server.py:test_server_outputs_ready_marker, tests/test_ai_server.py:test_server_starts_and_exits_cleanly, tests/test_conductor_engine_abort.py:worker, tests/test_parallel_execution.py:test_worker_pool_limit]
|
||||
"""
|
||||
start_time = time.time()
|
||||
with self._condition:
|
||||
while not self._done:
|
||||
@@ -1945,10 +1942,7 @@ class AppController:
|
||||
f.write(data)
|
||||
|
||||
def init_state(self):
|
||||
"""
|
||||
Initializes the application state from configurations.
|
||||
[C: src/gui_2.py:App.__init__, src/gui_2.py:App._save_paths, src/gui_2.py:App._set_external_editor_default, tests/test_app_controller_mcp.py:test_app_controller_mcp_loading, tests/test_app_controller_mcp.py:test_app_controller_mcp_project_override, tests/test_context_composition_decoupled.py:test_do_generate_uses_context_files, tests/test_external_mcp_e2e.py:test_external_mcp_e2e_refresh_and_call, tests/test_system_prompt_exposure.py:TestSystemPromptExposure.test_app_controller_init_state_loads_prompts]
|
||||
"""
|
||||
"""Initializes the application state from configurations."""
|
||||
self.active_tickets = []
|
||||
self.ui_separate_task_dag = False
|
||||
self.ui_separate_usage_analytics = False
|
||||
@@ -2119,9 +2113,6 @@ class AppController:
|
||||
self.event_queue.put('refresh_external_mcps', None)
|
||||
|
||||
async def refresh_external_mcps(self):
|
||||
"""
|
||||
[C: tests/test_external_mcp_e2e.py:test_external_mcp_e2e_refresh_and_call]
|
||||
"""
|
||||
await mcp_client.get_external_mcp_manager().stop_all()
|
||||
# Start servers with auto_start=True
|
||||
for name, cfg in self.mcp_config.mcpServers.items():
|
||||
@@ -2199,9 +2190,6 @@ class AppController:
|
||||
)])
|
||||
|
||||
def cb_load_prior_log(self, path: Optional[str] = None) -> None:
|
||||
"""
|
||||
[C: src/gui_2.py:App._render_log_management, src/gui_2.py:App.cb_load_prior_log]
|
||||
"""
|
||||
if not path:
|
||||
return
|
||||
|
||||
@@ -2614,7 +2602,8 @@ class AppController:
|
||||
|
||||
def warmup_canaries(self) -> list[dict]:
|
||||
"""
|
||||
Per-module import canary records. Each record carries: canary_id, module, thread_name, thread_id, submit_ts, start_ts, end_ts, elapsed_ms, status, error. Useful for debugging which worker thread loaded which module and how long it took. Returns a defensive copy (caller mutation is safe). [SDM: src/app_controller.py:warmup_canaries].
|
||||
Per-module import canary records. Each record carries: canary_id, module, thread_name, thread_id, submit_ts, start_ts, end_ts, elapsed_ms, status, error.
|
||||
Useful for debugging which worker thread loaded which module and how long it took. Returns a defensive copy (caller mutation is safe). [SDM: src/app_controller.py:warmup_canaries].
|
||||
"""
|
||||
return self._warmup.canaries()
|
||||
|
||||
@@ -2701,7 +2690,6 @@ class AppController:
|
||||
if the io_pool is still processing jobs from a prior test, submitting
|
||||
a new project switch would queue behind them and the switch would
|
||||
not complete promptly.
|
||||
[C: tests/test_live_workflow.py:test_full_live_workflow]
|
||||
"""
|
||||
return getattr(self, "_io_pool_inflight", 0) == 0
|
||||
|
||||
@@ -2717,7 +2705,6 @@ class AppController:
|
||||
def shutdown(self) -> None:
|
||||
"""
|
||||
Stops background threads and cleans up resources.
|
||||
[C: src/gui_2.py:App.run, src/gui_2.py:App.shutdown, tests/conftest.py:app_instance, tests/conftest.py:mock_app]
|
||||
"""
|
||||
from src import ai_client
|
||||
ai_client.cleanup()
|
||||
@@ -2823,7 +2810,6 @@ class AppController:
|
||||
"""
|
||||
Creates and configures the FastAPI application for headless mode.
|
||||
[SDM: src/app_controller.py:AppController.create_api]
|
||||
[C: src/gui_2.py:App.run, tests/test_headless_service.py:TestHeadlessAPI.setUp]
|
||||
"""
|
||||
fastapi = _require_warmed("fastapi")
|
||||
FastAPI = fastapi.FastAPI
|
||||
@@ -2841,21 +2827,12 @@ class AppController:
|
||||
return _api_health(self)
|
||||
@api.get("/api/gui/state", dependencies=[Depends(get_api_key)])
|
||||
def get_gui_state() -> Metadata:
|
||||
"""
|
||||
[C: tests/test_ai_settings_layout.py:test_change_provider_via_hook, tests/test_ai_settings_layout.py:test_set_params_via_custom_callback, tests/test_conductor_api_hook_integration.py:simulate_conductor_phase_completion, tests/test_external_editor_gui.py:test_button_click_is_received, tests/test_external_editor_gui.py:test_patch_modal_shows_with_configured_editor, tests/test_external_editor_gui.py:test_vscode_launches_with_diff_view, tests/test_gui_text_viewer.py:test_text_viewer_state_update, tests/test_hooks.py:test_live_hook_server_responses, tests/test_live_gui_integration_v2.py:test_api_gui_state_live, tests/test_live_workflow.py:test_full_live_workflow, tests/test_live_workflow.py:wait_for_value, tests/test_patch_modal_gui.py:test_patch_apply_modal_workflow, tests/test_patch_modal_gui.py:test_patch_modal_appears_on_trigger, tests/test_rag_phase4_final_verify.py:test_phase4_final_verify, tests/test_rag_phase4_stress.py:test_rag_large_codebase_verification_sim, tests/test_saved_presets_sim.py:test_preset_manager_modal, tests/test_saved_presets_sim.py:test_preset_switching, tests/test_task_dag_popout_sim.py:test_task_dag_popout, tests/test_tool_management_layout.py:test_tool_management_gettable_fields, tests/test_tool_management_layout.py:test_tool_management_state_updates, tests/test_tool_presets_sim.py:test_tool_preset_switching, tests/test_usage_analytics_popout_sim.py:test_usage_analytics_popout, tests/test_visual_mma.py:test_visual_mma_components]
|
||||
"""
|
||||
return _api_get_gui_state(self)
|
||||
@api.get("/api/gui/mma_status", dependencies=[Depends(get_api_key)])
|
||||
def get_mma_status() -> Metadata:
|
||||
"""
|
||||
[C: tests/test_headless_simulation.py:test_mma_track_lifecycle_simulation, tests/test_live_workflow.py:test_full_live_workflow, tests/test_mma_concurrent_tracks_sim.py:_poll_mma_status, tests/test_mma_concurrent_tracks_sim.py:test_mma_concurrent_tracks_execution, tests/test_mma_concurrent_tracks_stress_sim.py:test_mma_concurrent_tracks_stress, tests/test_mma_step_mode_sim.py:_poll_mma_status, tests/test_mma_step_mode_sim.py:test_mma_step_mode_approval_flow, tests/test_visual_mma.py:test_visual_mma_components, tests/test_visual_orchestration.py:test_mma_epic_lifecycle, tests/test_visual_sim_gui_ux.py:test_gui_ux_event_routing, tests/test_visual_sim_mma_v2.py:_poll]
|
||||
"""
|
||||
return _api_get_mma_status(self)
|
||||
@api.post("/api/gui", dependencies=[Depends(get_api_key)])
|
||||
def post_gui(req: dict) -> dict[str, str]:
|
||||
"""
|
||||
[C: tests/test_ai_settings_layout.py:test_set_params_via_custom_callback, tests/test_api_hook_client.py:test_post_gui_success, tests/test_gui2_parity.py:test_gui2_custom_callback_hook_works, tests/test_gui2_parity.py:test_gui2_set_value_hook_works]
|
||||
"""
|
||||
return _api_post_gui(self, req)
|
||||
@api.get("/api/session", dependencies=[Depends(get_api_key)])
|
||||
def get_api_session() -> Metadata:
|
||||
@@ -2895,18 +2872,12 @@ class AppController:
|
||||
return _api_list_sessions(self)
|
||||
@api.get("/api/v1/sessions/{session_id}", dependencies=[Depends(get_api_key)])
|
||||
def get_session(session_id: str) -> Metadata:
|
||||
"""
|
||||
[C: simulation/ping_pong.py:main, simulation/sim_context.py:ContextSimulation.run, simulation/sim_execution.py:ExecutionSimulation.run, simulation/sim_tools.py:ToolsSimulation.run, simulation/workflow_sim.py:WorkflowSimulator.run_discussion_turn_async, simulation/workflow_sim.py:WorkflowSimulator.wait_for_ai_response, tests/test_api_hook_client.py:test_get_session_success, tests/test_gui_stress_performance.py:test_comms_volume_stress_performance, tests/test_live_workflow.py:test_full_live_workflow, tests/test_rag_phase4_final_verify.py:test_phase4_final_verify, tests/test_rag_phase4_stress.py:test_rag_large_codebase_verification_sim]
|
||||
"""
|
||||
return _api_get_session(self, session_id)
|
||||
@api.delete("/api/v1/sessions/{session_id}", dependencies=[Depends(get_api_key)])
|
||||
def delete_session(session_id: str) -> dict[str, str]:
|
||||
return _api_delete_session(self, session_id)
|
||||
@api.get("/api/v1/context", dependencies=[Depends(get_api_key)])
|
||||
def get_context() -> Metadata:
|
||||
"""
|
||||
[C: src/fuzzy_anchor.py:FuzzyAnchor.create_slice]
|
||||
"""
|
||||
return _api_get_context(self)
|
||||
@api.get("/api/v1/token_stats", dependencies=[Depends(get_api_key)])
|
||||
def token_stats() -> Metadata:
|
||||
@@ -2914,17 +2885,12 @@ class AppController:
|
||||
return api
|
||||
|
||||
def clear_last_error(self) -> None:
|
||||
"""Reset last_error after a successful response cycle.
|
||||
[C: src/vendor_state.py:get_vendor_state]
|
||||
"""
|
||||
"""Reset last_error after a successful response cycle."""
|
||||
self.last_error = None
|
||||
|
||||
#region: Layout
|
||||
|
||||
def _cb_save_workspace_profile(self, name: str, scope: str = 'project') -> None:
|
||||
"""
|
||||
[C: src/gui_2.py:App._render_save_workspace_profile_modal]
|
||||
"""
|
||||
if not hasattr(self, '_app') or not self._app:
|
||||
return
|
||||
profile = self._app._capture_workspace_profile(name)
|
||||
@@ -2933,18 +2899,12 @@ class AppController:
|
||||
self._app.workspace_profiles = self.workspace_profiles
|
||||
|
||||
def _cb_delete_workspace_profile(self, name: str, scope: str = 'project') -> None:
|
||||
"""
|
||||
[C: src/gui_2.py:App._show_menus]
|
||||
"""
|
||||
self.workspace_manager.delete_profile(name, scope=scope)
|
||||
self.workspace_profiles = self.workspace_manager.load_all_profiles()
|
||||
if hasattr(self, '_app') and self._app:
|
||||
self._app.workspace_profiles = self.workspace_profiles
|
||||
|
||||
def _cb_load_workspace_profile(self, name: str) -> None:
|
||||
"""
|
||||
[C: src/gui_2.py:App._show_menus]
|
||||
"""
|
||||
if name in self.workspace_profiles:
|
||||
profile = self.workspace_profiles[name]
|
||||
if hasattr(self, '_app') and self._app:
|
||||
@@ -2955,9 +2915,6 @@ class AppController:
|
||||
#region: Serialization
|
||||
|
||||
def _flush_to_project(self) -> None:
|
||||
"""
|
||||
[C: src/gui_2.py:App._render_discussion_entry_controls, src/gui_2.py:App._render_main_interface, src/gui_2.py:App._render_projects_panel, src/gui_2.py:App._show_menus, tests/test_view_presets.py:test_save_view_preset]
|
||||
"""
|
||||
proj = self.project
|
||||
proj.setdefault("output", {})["output_dir"] = self.ui_output_dir
|
||||
proj.setdefault("files", {})["base_dir"] = self.ui_files_base_dir
|
||||
@@ -3003,9 +2960,6 @@ class AppController:
|
||||
)
|
||||
|
||||
def _flush_to_config(self) -> None:
|
||||
"""
|
||||
[C: src/gui_2.py:App._render_discussion_entry_controls, src/gui_2.py:App._render_main_interface, src/gui_2.py:App._render_projects_panel, src/gui_2.py:App._render_theme_panel, src/gui_2.py:App._show_menus, tests/test_system_prompt_exposure.py:TestSystemPromptExposure.test_app_controller_flush_saves_prompts]
|
||||
"""
|
||||
self.config["ai"] = {
|
||||
"provider": self.current_provider,
|
||||
"model": self.current_model,
|
||||
@@ -3085,9 +3039,6 @@ class AppController:
|
||||
}
|
||||
|
||||
def _refresh_api_metrics(self, payload: Metadata, md_content: str | None = None) -> None:
|
||||
"""
|
||||
[C: tests/test_gui_updates.py:test_telemetry_data_updates_correctly]
|
||||
"""
|
||||
if "latency" in payload:
|
||||
self.session_usage["last_latency"] = payload["latency"]
|
||||
if "usage" in payload and "percentage" in payload["usage"]:
|
||||
@@ -3112,9 +3063,7 @@ class AppController:
|
||||
self._update_cached_stats()
|
||||
|
||||
def set_vendor_quota(self, provider: str, remaining_pct: float, reset_at: str = "") -> None:
|
||||
"""Update vendor quota state from a quota-bearing API response.
|
||||
[C: src/vendor_state.py:get_vendor_state]
|
||||
"""
|
||||
"""Update vendor quota state from a quota-bearing API response."""
|
||||
self.vendor_quota = {"provider": provider, "remaining_pct": remaining_pct, "reset_at": reset_at}
|
||||
|
||||
def _recalculate_session_usage(self) -> None:
|
||||
@@ -3205,8 +3154,6 @@ class AppController:
|
||||
|
||||
def _switch_project(self, path: str) -> None:
|
||||
"""
|
||||
[C: src/gui_2.py:App._render_projects_panel]
|
||||
|
||||
Non-blocking: returns immediately, marks the controller as stale,
|
||||
and runs the actual save/load work in a background thread so the
|
||||
render loop keeps drawing and lightweight UI interactions (scrolling,
|
||||
@@ -3231,9 +3178,6 @@ class AppController:
|
||||
|
||||
def _refresh_from_project(self) -> None:
|
||||
# Deserialize FileItems in files.paths
|
||||
"""
|
||||
[C: tests/test_mma_dashboard_refresh.py:test_mma_dashboard_initialization_refresh, tests/test_mma_dashboard_refresh.py:test_mma_dashboard_refresh, tests/test_view_presets.py:test_load_presets_from_project_legacy_dict, tests/test_view_presets.py:test_load_presets_from_project_list]
|
||||
"""
|
||||
raw_paths = self.project.get("files", {}).get("paths", [])
|
||||
self.files = []
|
||||
for p in raw_paths:
|
||||
@@ -3342,9 +3286,6 @@ class AppController:
|
||||
return False
|
||||
|
||||
def _save_active_project(self) -> None:
|
||||
"""
|
||||
[C: src/gui_2.py:App.delete_context_preset, src/gui_2.py:App.save_context_preset]
|
||||
"""
|
||||
result = self._save_active_project_result()
|
||||
if not result.ok:
|
||||
err = result.errors[0]
|
||||
@@ -3377,9 +3318,6 @@ class AppController:
|
||||
#region: Context
|
||||
|
||||
def _cb_reset_base_prompt(self, user_data=None) -> None:
|
||||
"""
|
||||
[C: src/gui_2.py:App._render_system_prompts_panel]
|
||||
"""
|
||||
self.ui_base_system_prompt = ai_client._SYSTEM_PROMPT
|
||||
self.ui_use_default_base_prompt = False
|
||||
|
||||
@@ -3388,15 +3326,9 @@ class AppController:
|
||||
self.ai_status = 'summary cache cleared'
|
||||
|
||||
def _cb_show_base_prompt_diff(self, user_data=None) -> None:
|
||||
"""
|
||||
[C: src/gui_2.py:App._render_system_prompts_panel]
|
||||
"""
|
||||
self._show_base_prompt_diff_modal = True
|
||||
|
||||
def _cb_clear_summary_cache(self, user_data=None) -> None:
|
||||
"""
|
||||
[C: src/gui_2.py:App._render_files_panel]
|
||||
"""
|
||||
from src import summarize
|
||||
summarize._summary_cache.clear()
|
||||
self._push_mma_state_update()
|
||||
@@ -3434,9 +3366,6 @@ class AppController:
|
||||
self._cached_tool_stats = dict(self._tool_stats)
|
||||
|
||||
def clear_cache(self) -> None:
|
||||
"""
|
||||
[C: src/gui_2.py:App._render_cache_panel]
|
||||
"""
|
||||
from src import ai_client
|
||||
ai_client.cleanup()
|
||||
self._update_cached_stats()
|
||||
@@ -3651,9 +3580,6 @@ class AppController:
|
||||
self.ui_project_preset_name = name
|
||||
|
||||
def _cb_save_preset(self, name, content, scope):
|
||||
"""
|
||||
[C: src/gui_2.py:App._render_preset_manager_content]
|
||||
"""
|
||||
if not name or not name.strip():
|
||||
raise ValueError("Preset name cannot be empty or whitespace.")
|
||||
preset = Preset(
|
||||
@@ -3664,31 +3590,19 @@ class AppController:
|
||||
self.presets = self.preset_manager.load_all()
|
||||
|
||||
def _cb_delete_preset(self, name, scope):
|
||||
"""
|
||||
[C: src/gui_2.py:App._render_preset_manager_content]
|
||||
"""
|
||||
self.preset_manager.delete_preset(name, scope)
|
||||
self.presets = self.preset_manager.load_all()
|
||||
|
||||
def _cb_save_tool_preset(self, name, categories, scope):
|
||||
"""
|
||||
[C: src/gui_2.py:App._render_tool_preset_manager_content]
|
||||
"""
|
||||
preset = ToolPreset(name=name, categories=categories)
|
||||
self.tool_preset_manager.save_preset(preset, scope)
|
||||
self.tool_presets = self.tool_preset_manager.load_all_presets()
|
||||
|
||||
def _cb_delete_tool_preset(self, name, scope):
|
||||
"""
|
||||
[C: src/gui_2.py:App._render_tool_preset_manager_content]
|
||||
"""
|
||||
self.tool_preset_manager.delete_preset(name, scope)
|
||||
self.tool_presets = self.tool_preset_manager.load_all_presets()
|
||||
|
||||
def _cb_save_bias_profile(self, profile: BiasProfile, scope: str = "project"):
|
||||
"""
|
||||
[C: src/gui_2.py:App._render_tool_preset_manager_content]
|
||||
"""
|
||||
self.tool_preset_manager.save_bias_profile(profile, scope)
|
||||
self.bias_profiles = self.tool_preset_manager.load_all_bias_profiles()
|
||||
|
||||
@@ -3697,23 +3611,14 @@ class AppController:
|
||||
self.bias_profiles = self.tool_preset_manager.load_all_bias_profiles()
|
||||
|
||||
def _cb_save_persona(self, persona: Persona, scope: str = "project") -> None:
|
||||
"""
|
||||
[C: src/gui_2.py:App._render_persona_editor_window]
|
||||
"""
|
||||
self.persona_manager.save_persona(persona, scope)
|
||||
self.personas = self.persona_manager.load_all()
|
||||
|
||||
def _cb_delete_persona(self, name: str, scope: str = "project") -> None:
|
||||
"""
|
||||
[C: src/gui_2.py:App._render_persona_editor_window]
|
||||
"""
|
||||
self.persona_manager.delete_persona(name, scope)
|
||||
self.personas = self.persona_manager.load_all()
|
||||
|
||||
def _cb_save_view_preset(self, name: str, f_item: FileItem) -> None:
|
||||
"""
|
||||
[C: src/gui_2.py:App._render_context_files_table, tests/test_view_presets.py:test_save_view_preset]
|
||||
"""
|
||||
preset = NamedViewPreset(
|
||||
name=name,
|
||||
view_mode=f_item.view_mode,
|
||||
@@ -3729,9 +3634,6 @@ class AppController:
|
||||
self._flush_to_project()
|
||||
|
||||
def _cb_apply_view_preset(self, name: str, f_item: FileItem) -> None:
|
||||
"""
|
||||
[C: src/gui_2.py:App._render_context_files_table, tests/test_view_presets.py:test_apply_view_preset]
|
||||
"""
|
||||
preset = next((vp for vp in self.view_presets if vp.name == name), None)
|
||||
if preset:
|
||||
f_item.view_mode = preset.view_mode
|
||||
@@ -3739,9 +3641,6 @@ class AppController:
|
||||
f_item.custom_slices = copy.deepcopy(preset.custom_slices)
|
||||
|
||||
def _cb_delete_view_preset(self, name: str) -> None:
|
||||
"""
|
||||
[C: tests/test_view_presets.py:test_delete_view_preset]
|
||||
"""
|
||||
self.view_presets = [vp for vp in self.view_presets if vp.name != name]
|
||||
self._flush_to_project()
|
||||
|
||||
@@ -3756,17 +3655,11 @@ class AppController:
|
||||
self.ui_disc_new_name_input = ""
|
||||
|
||||
def _get_discussion_names(self) -> list[str]:
|
||||
"""
|
||||
[C: src/gui_2.py:App._render_discussion_selector, src/gui_2.py:App._render_theme_panel]
|
||||
"""
|
||||
disc_sec = self.project.get("discussion", {})
|
||||
discussions = disc_sec.get("discussions", {})
|
||||
return sorted(discussions.keys())
|
||||
|
||||
def _switch_discussion(self, name: str) -> None:
|
||||
"""
|
||||
[C: src/gui_2.py:App._render_discussion_selector, src/gui_2.py:App._render_takes_panel, src/gui_2.py:App._render_theme_panel]
|
||||
"""
|
||||
self._flush_disc_entries_to_project()
|
||||
disc_sec = self.project.get("discussion", {})
|
||||
discussions = disc_sec.get("discussions", {})
|
||||
@@ -3790,9 +3683,6 @@ class AppController:
|
||||
self.ai_status = f"discussion: {name}"
|
||||
|
||||
def _flush_disc_entries_to_project(self) -> None:
|
||||
"""
|
||||
[C: src/gui_2.py:App._render_discussion_selector, src/gui_2.py:App._render_theme_panel]
|
||||
"""
|
||||
history_strings = [project_manager.entry_to_str(e) for e in self.disc_entries]
|
||||
if self.active_track and self._track_discussion_active:
|
||||
project_manager.save_track_history(self.active_track.id, history_strings, self.active_project_root)
|
||||
@@ -3807,10 +3697,7 @@ class AppController:
|
||||
disc_data["sent_system_prompt"] = getattr(self, "discussion_sent_system_prompt", "")
|
||||
|
||||
def _handle_approve_ask(self) -> None:
|
||||
"""
|
||||
Responds with approval for a pending /api/ask request.
|
||||
[C: src/gui_2.py:App._handle_approve_ask, src/gui_2.py:App._render_mma_modals]
|
||||
"""
|
||||
"""Responds with approval for a pending /api/ask request."""
|
||||
if not self._ask_request_id: return
|
||||
request_id = self._ask_request_id
|
||||
|
||||
@@ -3829,10 +3716,7 @@ class AppController:
|
||||
self._ask_tool_data = None
|
||||
|
||||
def _handle_reject_ask(self) -> None:
|
||||
"""
|
||||
Responds with rejection for a pending /api/ask request.
|
||||
[C: src/gui_2.py:App._render_mma_modals]
|
||||
"""
|
||||
"""Responds with rejection for a pending /api/ask request."""
|
||||
if not self._ask_request_id: return
|
||||
request_id = self._ask_request_id
|
||||
|
||||
@@ -3851,10 +3735,7 @@ class AppController:
|
||||
self._ask_tool_data = None
|
||||
|
||||
def _handle_reset_session(self) -> None:
|
||||
"""
|
||||
Logic for resetting the AI session and GUI state.
|
||||
[C: src/gui_2.py:App._render_message_panel]
|
||||
"""
|
||||
"""Logic for resetting the AI session and GUI state."""
|
||||
ai_client.reset_session()
|
||||
ai_client.clear_comms_log()
|
||||
self._tool_log.clear()
|
||||
@@ -4021,18 +3902,12 @@ class AppController:
|
||||
self.submit_io(worker)
|
||||
|
||||
def _handle_generate_send(self) -> None:
|
||||
"""
|
||||
Logic for the 'Gen + Send' action.
|
||||
[C: src/gui_2.py:App._render_message_panel, src/gui_2.py:App._render_synthesis_panel, src/gui_2.py:App._render_takes_panel, tests/test_gui_events_v2.py:test_handle_generate_send_pushes_event, tests/test_symbol_parsing.py:test_handle_generate_send_appends_definitions, tests/test_symbol_parsing.py:test_handle_generate_send_no_symbols]
|
||||
"""
|
||||
"""Logic for the 'Gen + Send' action."""
|
||||
if self.is_project_stale():
|
||||
self.ai_status = "project switch in progress; AI ops disabled"
|
||||
return
|
||||
|
||||
def worker() -> "Result[None]":
|
||||
"""
|
||||
[C: tests/test_symbol_parsing.py:test_handle_generate_send_appends_definitions, tests/test_symbol_parsing.py:test_handle_generate_send_no_symbols]
|
||||
"""
|
||||
try:
|
||||
md, path, file_items, stable_md, disc_text = self._do_generate()
|
||||
self._last_stable_md = stable_md
|
||||
@@ -4064,10 +3939,7 @@ class AppController:
|
||||
self.submit_io(worker)
|
||||
|
||||
def _do_generate(self) -> tuple[str, Path, list[FileItem], str, str]:
|
||||
"""
|
||||
Returns (full_md, output_path, file_items, stable_md, discussion_text).
|
||||
[C: src/gui_2.py:App._show_menus, tests/test_context_composition_decoupled.py:test_do_generate_uses_context_files, tests/test_tiered_aggregation.py:test_app_controller_do_generate_uses_persona_strategy]
|
||||
"""
|
||||
"""Returns (full_md, output_path, file_items, stable_md, discussion_text)."""
|
||||
self._flush_to_project()
|
||||
self._flush_to_config()
|
||||
self.save_config()
|
||||
@@ -4114,18 +3986,12 @@ class AppController:
|
||||
return full_md, path, file_items, stable_md, discussion_text
|
||||
|
||||
def _handle_md_only(self) -> None:
|
||||
"""
|
||||
Logic for the 'MD Only' action.
|
||||
[C: src/gui_2.py:App._render_message_panel]
|
||||
"""
|
||||
"""Logic for the 'MD Only' action."""
|
||||
if self.is_project_stale():
|
||||
self.ai_status = "project switch in progress; MD generation disabled"
|
||||
return
|
||||
|
||||
def worker() -> "Result[None]":
|
||||
"""
|
||||
[C: tests/test_symbol_parsing.py:test_handle_generate_send_appends_definitions, tests/test_symbol_parsing.py:test_handle_generate_send_no_symbols]
|
||||
"""
|
||||
try:
|
||||
md, path, *_ = self._do_generate()
|
||||
self.last_md = md
|
||||
@@ -4144,9 +4010,6 @@ class AppController:
|
||||
self.submit_io(worker)
|
||||
|
||||
def _create_discussion(self, name: str) -> None:
|
||||
"""
|
||||
[C: src/gui_2.py:App._render_discussion_metadata, src/gui_2.py:App._render_synthesis_panel, src/gui_2.py:App._render_takes_panel]
|
||||
"""
|
||||
disc_sec = self.project.setdefault("discussion", {})
|
||||
discussions = disc_sec.setdefault("discussions", {})
|
||||
if name in discussions:
|
||||
@@ -4160,9 +4023,6 @@ class AppController:
|
||||
self._switch_discussion(name)
|
||||
|
||||
def _branch_discussion(self, index: int) -> None:
|
||||
"""
|
||||
[C: src/gui_2.py:App._render_discussion_entry]
|
||||
"""
|
||||
self._flush_disc_entries_to_project()
|
||||
# Generate a unique branch name
|
||||
base_name = self.active_discussion.split("_take_")[0]
|
||||
@@ -4178,9 +4038,6 @@ class AppController:
|
||||
self._switch_discussion(new_name)
|
||||
|
||||
def _rename_discussion(self, old_name: str, new_name: str) -> None:
|
||||
"""
|
||||
[C: src/gui_2.py:App._render_discussion_metadata]
|
||||
"""
|
||||
disc_sec = self.project.get("discussion", {})
|
||||
discussions = disc_sec.get("discussions", {})
|
||||
if old_name not in discussions:
|
||||
@@ -4194,9 +4051,6 @@ class AppController:
|
||||
disc_sec["active"] = new_name
|
||||
|
||||
def _delete_discussion(self, name: str) -> None:
|
||||
"""
|
||||
[C: src/gui_2.py:App._render_discussion_metadata]
|
||||
"""
|
||||
disc_sec = self.project.get("discussion", {})
|
||||
discussions = disc_sec.get("discussions", {})
|
||||
if len(discussions) <= 1:
|
||||
@@ -4214,10 +4068,7 @@ class AppController:
|
||||
#region: Operations
|
||||
|
||||
def _handle_request_event(self, event: events.UserRequestEvent) -> None:
|
||||
"""
|
||||
Processes a UserRequestEvent by calling the AI client.
|
||||
[C: tests/test_live_gui_integration_v2.py:test_user_request_error_handling, tests/test_live_gui_integration_v2.py:test_user_request_integration_flow, tests/test_rag_integration.py:test_rag_integration]
|
||||
"""
|
||||
"""Processes a UserRequestEvent by calling the AI client."""
|
||||
self.ai_status = 'sending...'
|
||||
|
||||
user_msg = event.prompt
|
||||
@@ -4295,9 +4146,6 @@ class AppController:
|
||||
self._ai_status = f"error: {err.ui_message()}"
|
||||
|
||||
def _on_tool_log(self, script: str, result: str) -> None:
|
||||
"""
|
||||
[C: tests/test_app_controller_offloading.py:test_on_tool_log_offloading]
|
||||
"""
|
||||
session_logger.log_tool_call(script, result, None)
|
||||
session_logger.log_tool_output_result(result)
|
||||
source_tier = ai_client.get_current_tier_result().data
|
||||
@@ -4325,9 +4173,6 @@ class AppController:
|
||||
return optimized
|
||||
|
||||
def _on_api_event(self, event_name: str = "generic_event", **kwargs: Any) -> None:
|
||||
"""
|
||||
[C: tests/test_gui_updates.py:test_gui_updates_on_event]
|
||||
"""
|
||||
payload = kwargs.get("payload", {})
|
||||
# Push to background event queue, NOT GUI queue
|
||||
self.event_queue.put("refresh_api_metrics", payload)
|
||||
@@ -4347,9 +4192,6 @@ class AppController:
|
||||
if self._ai_status not in ("sending...", "streaming..."):
|
||||
self._ai_status = "streaming..."
|
||||
def _on_comms_entry(self, entry: Metadata) -> None:
|
||||
"""
|
||||
[C: tests/test_app_controller_offloading.py:test_on_comms_entry_tool_result_offloading]
|
||||
"""
|
||||
optimized_entry = self._offload_entry_payload(entry)
|
||||
session_logger.log_comms(optimized_entry)
|
||||
entry["local_ts"] = time.time()
|
||||
@@ -4446,9 +4288,6 @@ class AppController:
|
||||
self._pending_comms.append(entry)
|
||||
|
||||
def _append_tool_log(self, script: str, result: str, source_tier: str | None = None, elapsed_ms: float = 0.0) -> None:
|
||||
"""
|
||||
[C: tests/test_mma_agent_focus_phase1.py:test_append_tool_log_dict_has_source_tier, tests/test_mma_agent_focus_phase1.py:test_append_tool_log_dict_keys, tests/test_mma_agent_focus_phase1.py:test_append_tool_log_stores_dict]
|
||||
"""
|
||||
self._tool_log.append({"script": script, "result": result, "ts": time.time(), "source_tier": source_tier})
|
||||
tool_name = self._extract_tool_name(script)
|
||||
is_failure = "REJECTED" in result or "Error" in result or "error" in result.lower()
|
||||
@@ -4467,9 +4306,6 @@ class AppController:
|
||||
self._scroll_tool_calls_to_bottom = True
|
||||
|
||||
def _confirm_and_run(self, script: str, base_dir: str, qa_callback: Optional[Callable[[str], str]] = None, patch_callback: Optional[Callable[[str, str], Result[str]]] = None) -> str:
|
||||
"""
|
||||
[C: tests/test_arch_boundary_phase2.py:TestArchBoundaryPhase2.test_mutating_tool_triggers_callback, tests/test_arch_boundary_phase2.py:TestArchBoundaryPhase2.test_rejection_prevents_dispatch]
|
||||
"""
|
||||
if self.test_hooks_enabled and not getattr(self, "ui_manual_approve", False):
|
||||
self.ai_status = "running powershell..."
|
||||
output = shell_runner.run_powershell(script, base_dir, qa_callback=qa_callback, patch_callback=patch_callback)
|
||||
@@ -4627,9 +4463,6 @@ class AppController:
|
||||
asyncio.run(self.refresh_external_mcps())
|
||||
|
||||
def _cb_plan_epic(self) -> None:
|
||||
"""
|
||||
[C: src/gui_2.py:App._render_mma_epic_planner, tests/test_mma_orchestration_gui.py:test_cb_plan_epic_launches_thread]
|
||||
"""
|
||||
def _bg_task() -> "Result[None]":
|
||||
try:
|
||||
self.ai_status = "Planning Epic (Tier 1)..."
|
||||
@@ -4681,9 +4514,6 @@ class AppController:
|
||||
self.submit_io(_bg_task)
|
||||
|
||||
def _cb_accept_tracks(self) -> None:
|
||||
"""
|
||||
[C: src/gui_2.py:App._render_track_proposal_modal]
|
||||
"""
|
||||
self._show_track_proposal_modal = False
|
||||
|
||||
def _bg_task() -> "Result[None]":
|
||||
@@ -4728,9 +4558,6 @@ class AppController:
|
||||
self.submit_io(_bg_task)
|
||||
|
||||
def _cb_start_track(self, user_data: Any = None) -> None:
|
||||
"""
|
||||
[C: src/gui_2.py:App._render_track_proposal_modal]
|
||||
"""
|
||||
if isinstance(user_data, str):
|
||||
# If track_id is provided directly
|
||||
track_id = user_data
|
||||
@@ -4882,9 +4709,6 @@ class AppController:
|
||||
return Result(data=None, errors=[err])
|
||||
|
||||
def _cb_ticket_retry(self, ticket_id: str) -> None:
|
||||
"""
|
||||
[C: tests/test_mma_ticket_actions.py:test_cb_ticket_retry]
|
||||
"""
|
||||
for t in self.active_tickets:
|
||||
if t.id == ticket_id:
|
||||
t.status = 'todo'
|
||||
@@ -4892,9 +4716,6 @@ class AppController:
|
||||
self.event_queue.put("mma_retry", {"ticket_id": ticket_id})
|
||||
|
||||
def _cb_ticket_skip(self, ticket_id: str) -> None:
|
||||
"""
|
||||
[C: tests/test_mma_ticket_actions.py:test_cb_ticket_skip]
|
||||
"""
|
||||
for t in self.active_tickets:
|
||||
if t.id == ticket_id:
|
||||
t.status = 'skipped'
|
||||
@@ -4914,10 +4735,7 @@ class AppController:
|
||||
self.event_queue.put("mma_retry", {"ticket_id": ticket_id})
|
||||
|
||||
def kill_worker(self, worker_id: str) -> None:
|
||||
"""
|
||||
Aborts a running worker.
|
||||
[C: src/gui_2.py:App._cb_kill_ticket, tests/test_conductor_engine_abort.py:test_kill_worker_sets_abort_and_joins_thread]
|
||||
"""
|
||||
"""Aborts a running worker."""
|
||||
engine = self.engines.get(self.active_track.id if self.active_track else None)
|
||||
if engine:
|
||||
engine.kill_worker(worker_id)
|
||||
@@ -4987,9 +4805,6 @@ class AppController:
|
||||
)])
|
||||
|
||||
def _cb_run_conductor_setup(self) -> None:
|
||||
"""
|
||||
[C: src/gui_2.py:App._render_mma_conductor_setup, tests/test_gui_phase3.py:test_conductor_setup_scan]
|
||||
"""
|
||||
base = paths.get_conductor_dir(project_path=self.active_project_root)
|
||||
if not base.exists():
|
||||
self.ui_conductor_setup_summary = f"Error: {base}/ directory not found."
|
||||
@@ -5017,9 +4832,6 @@ class AppController:
|
||||
self.ui_conductor_setup_summary = "\n".join(summary)
|
||||
|
||||
def _cb_create_track(self, name: str, desc: str, track_type: str) -> None:
|
||||
"""
|
||||
[C: src/gui_2.py:App._render_mma_track_browser, tests/test_gui_phase3.py:test_create_track]
|
||||
"""
|
||||
if not name: return
|
||||
date_suffix = datetime.now().strftime("%Y%m%d")
|
||||
track_id = f"{name.lower().replace(' ', '_')}_{date_suffix}"
|
||||
@@ -5045,9 +4857,6 @@ class AppController:
|
||||
self.tracks = project_manager.get_all_tracks(self.active_project_root)
|
||||
|
||||
def _handle_mma_respond(self, approved: bool, payload: str | None = None, abort: bool = False, prompt: str | None = None, context_md: str | None = None) -> None:
|
||||
"""
|
||||
[C: src/gui_2.py:App._handle_approve_mma_step, src/gui_2.py:App._handle_approve_spawn, src/gui_2.py:App._render_mma_modals]
|
||||
"""
|
||||
if self._pending_mma_approvals:
|
||||
task = self._pending_mma_approvals.pop(0)
|
||||
dlg = task.get("dialog_container", [None])[0]
|
||||
@@ -5164,7 +4973,6 @@ class AppController:
|
||||
DEPRECATED (Phase 7 Task 7.4): legacy fire-and-forget wrapper. New
|
||||
callers should use `_push_mma_state_update_result()` which returns
|
||||
Result[None] and propagates errors via `_report_worker_error`.
|
||||
[C: tests/test_gui_phase4.py:test_push_mma_state_update, tests/test_ticket_queue.py:TestBulkOperations, tests/test_ticket_queue.py:TestReorder]
|
||||
"""
|
||||
result = self._push_mma_state_update_result()
|
||||
if not result.ok:
|
||||
@@ -5214,7 +5022,6 @@ class AppController:
|
||||
Otherwise, read from project state. The current code paths
|
||||
(mutate_dag, _cb_ticket_skip, etc.) populate self.active_tickets
|
||||
directly, so this method is the bootstrap path.
|
||||
[C: src/app_controller.py:_load_active_tickets call sites, tests/test_gui_dag_beads.py:test_load_active_tickets_from_beads]
|
||||
"""
|
||||
self.active_tickets = []
|
||||
if getattr(self, "ui_project_execution_mode", None) == "beads":
|
||||
@@ -5260,7 +5067,6 @@ class AppController:
|
||||
from outside the controller (e.g. models.load_config) are an
|
||||
architectural smell and will be flagged by
|
||||
scripts/audit_no_models_config_io.py.
|
||||
[C: src/app_controller.py:AppController.__init__]
|
||||
"""
|
||||
self.config = load_config_from_disk()
|
||||
return self.config
|
||||
@@ -5272,7 +5078,6 @@ class AppController:
|
||||
controller (e.g. models.save_config) are an architectural smell
|
||||
and will be flagged by
|
||||
scripts/audit_no_models_config_io.py.
|
||||
[C: src/app_controller.py:AppController._cb_project_save, src/app_controller.py:AppController._do_generate]
|
||||
"""
|
||||
save_config_to_disk(self.config)
|
||||
#endregion: --- Config I/O (single source of truth) ---
|
||||
@@ -5283,18 +5088,12 @@ class AppController:
|
||||
|
||||
class MMAApprovalDialog:
|
||||
def __init__(self, ticket_id: str, payload: str) -> None:
|
||||
"""
|
||||
[C: src/mcp_client.py:_DDGParser.__init__, src/mcp_client.py:_TextExtractor.__init__]
|
||||
"""
|
||||
self._payload = payload
|
||||
self._condition = threading.Condition()
|
||||
self._done = False
|
||||
self._approved = False
|
||||
|
||||
def wait(self) -> tuple[bool, str]:
|
||||
"""
|
||||
[C: src/mcp_client.py:StdioMCPServer.stop, src/multi_agent_conductor.py:confirm_execution, src/multi_agent_conductor.py:confirm_spawn, tests/conftest.py:live_gui, tests/test_ai_client_concurrency.py:run_t1, tests/test_ai_client_concurrency.py:run_t2, tests/test_ai_server.py:test_server_handles_list_models, tests/test_ai_server.py:test_server_handles_unknown_method, tests/test_ai_server.py:test_server_loads_google_genai_quickly, tests/test_ai_server.py:test_server_outputs_ready_marker, tests/test_ai_server.py:test_server_starts_and_exits_cleanly, tests/test_conductor_engine_abort.py:worker, tests/test_parallel_execution.py:test_worker_pool_limit]
|
||||
"""
|
||||
start_time = time.time()
|
||||
with self._condition:
|
||||
while not self._done:
|
||||
@@ -5305,9 +5104,6 @@ class MMAApprovalDialog:
|
||||
|
||||
class MMASpawnApprovalDialog:
|
||||
def __init__(self, ticket_id: str, role: str, prompt: str, context_md: str) -> None:
|
||||
"""
|
||||
[C: src/mcp_client.py:_DDGParser.__init__, src/mcp_client.py:_TextExtractor.__init__]
|
||||
"""
|
||||
self._prompt = prompt
|
||||
self._context_md = context_md
|
||||
self._condition = threading.Condition()
|
||||
@@ -5316,9 +5112,6 @@ class MMASpawnApprovalDialog:
|
||||
self._abort = False
|
||||
|
||||
def wait(self) -> Metadata:
|
||||
"""
|
||||
[C: src/mcp_client.py:StdioMCPServer.stop, src/multi_agent_conductor.py:confirm_execution, src/multi_agent_conductor.py:confirm_spawn, tests/conftest.py:live_gui, tests/test_ai_client_concurrency.py:run_t1, tests/test_ai_client_concurrency.py:run_t2, tests/test_ai_server.py:test_server_handles_list_models, tests/test_ai_server.py:test_server_handles_unknown_method, tests/test_ai_server.py:test_server_loads_google_genai_quickly, tests/test_ai_server.py:test_server_outputs_ready_marker, tests/test_ai_server.py:test_server_starts_and_exits_cleanly, tests/test_conductor_engine_abort.py:worker, tests/test_parallel_execution.py:test_worker_pool_limit]
|
||||
"""
|
||||
start_time = time.time()
|
||||
with self._condition:
|
||||
while not self._done:
|
||||
@@ -5333,4 +5126,3 @@ class MMASpawnApprovalDialog:
|
||||
}
|
||||
|
||||
#endregion: MMA
|
||||
|
||||
|
||||
Reference in New Issue
Block a user