refactor(app_controller): migrate 7 conductor/track sites to Result (batch 3)
Migrated 7 INTERNAL_BROAD_CATCH sites in src/app_controller.py: 1. _do_project_switch load (L2813) - project_manager.load_project - Narrowed: except Exception -> (OSError, IOError, ValueError, TypeError, KeyError, AttributeError, tomllib.TOMLDecodeError) - Returns Result[None] with errors on failure - Preserves the _project_switch_error state 2. _do_project_switch managers (L2825) - manager initialization - Same exception narrowing - Returns Result[None] with errors - Preserves the _project_switch_error state 3. _start_track_logic (L4304) - track creation + engine spawn - Narrowed: except Exception -> (OSError, IOError, ValueError, TypeError, KeyError, AttributeError, RuntimeError) - logging.debug added - Preserves the ai_status = Track start error 4. _cb_run_conductor_setup file read (L4416) - file iteration - Narrowed: except Exception -> (OSError, IOError, UnicodeDecodeError) - logging.debug with file path - Preserves the Error reading fallback 5. _cb_load_track (L4513) - project_manager.load_track_state - Narrowed: except Exception -> (OSError, IOError, ValueError, TypeError, KeyError, AttributeError, tomllib.TOMLDecodeError) - logging.debug added - Preserves the Load track error fallback 6. _push_mma_state_update (L4542) - project_manager.save_track_state - Narrowed: except Exception -> (OSError, IOError, ValueError, TypeError, KeyError, AttributeError) - logging.debug added - Preserves the print to stderr fallback 7. _load_active_tickets beads (L4571) - bclient.list_beads - Narrowed: except Exception -> (OSError, IOError, ValueError, TypeError, KeyError, AttributeError) - logging.debug added - Preserves the Error loading beads fallback Refs: spec.md FR1, plan.md Task 2.4
This commit is contained in:
+50
-16
@@ -2804,16 +2804,22 @@ class AppController:
|
|||||||
self.save_config()
|
self.save_config()
|
||||||
self.ai_status = "config saved"
|
self.ai_status = "config saved"
|
||||||
|
|
||||||
def _do_project_switch(self, path: str) -> None:
|
def _do_project_switch(self, path: str) -> Result[None]:
|
||||||
self._project_switch_error = None
|
self._project_switch_error = None
|
||||||
try:
|
try:
|
||||||
self._flush_to_project()
|
self._flush_to_project()
|
||||||
try:
|
try:
|
||||||
new_project = project_manager.load_project(path)
|
new_project = project_manager.load_project(path)
|
||||||
except Exception as e:
|
except (OSError, IOError, ValueError, TypeError, KeyError, AttributeError, tomllib.TOMLDecodeError) as e:
|
||||||
|
logging.getLogger(__name__).debug("project load failed: %s", e, extra={"source": "app_controller._do_project_switch.load"})
|
||||||
self.ai_status = f"failed to load project: {e}"
|
self.ai_status = f"failed to load project: {e}"
|
||||||
self._project_switch_error = f"load failed: {e}"
|
self._project_switch_error = f"load failed: {e}"
|
||||||
return
|
return Result(data=None, errors=[ErrorInfo(
|
||||||
|
kind=ErrorKind.INTERNAL,
|
||||||
|
message=str(e),
|
||||||
|
source="app_controller._do_project_switch.load",
|
||||||
|
original=e,
|
||||||
|
)])
|
||||||
try:
|
try:
|
||||||
self.project = new_project
|
self.project = new_project
|
||||||
self.active_project_path = path
|
self.active_project_path = path
|
||||||
@@ -2822,14 +2828,21 @@ class AppController:
|
|||||||
self.tool_preset_manager = tool_presets.ToolPresetManager(new_root)
|
self.tool_preset_manager = tool_presets.ToolPresetManager(new_root)
|
||||||
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 (OSError, IOError, ValueError, TypeError, KeyError, AttributeError) as e:
|
||||||
|
logging.getLogger(__name__).debug("manager init failed: %s", e, extra={"source": "app_controller._do_project_switch.managers"})
|
||||||
self.ai_status = f"failed to init managers: {e}"
|
self.ai_status = f"failed to init managers: {e}"
|
||||||
self._project_switch_error = f"manager init failed: {e}"
|
self._project_switch_error = f"manager init failed: {e}"
|
||||||
return
|
return Result(data=None, errors=[ErrorInfo(
|
||||||
|
kind=ErrorKind.INTERNAL,
|
||||||
|
message=str(e),
|
||||||
|
source="app_controller._do_project_switch.managers",
|
||||||
|
original=e,
|
||||||
|
)])
|
||||||
self._refresh_from_project()
|
self._refresh_from_project()
|
||||||
file_items_as_dicts = [{"path": f.path if hasattr(f, "path") else str(f)} for f in self.files]
|
file_items_as_dicts = [{"path": f.path if hasattr(f, "path") else str(f)} for f in self.files]
|
||||||
mcp_client.configure(file_items_as_dicts, [str(new_root)])
|
mcp_client.configure(file_items_as_dicts, [str(new_root)])
|
||||||
self.ai_status = f"switched to: {Path(path).stem}"
|
self.ai_status = f"switched to: {Path(path).stem}"
|
||||||
|
return OK
|
||||||
finally:
|
finally:
|
||||||
with self._project_switch_lock:
|
with self._project_switch_lock:
|
||||||
pending = self._project_switch_pending_path
|
pending = self._project_switch_pending_path
|
||||||
@@ -3079,7 +3092,7 @@ class AppController:
|
|||||||
if not self.rag_config or not self.rag_config.enabled or not self.rag_engine:
|
if not self.rag_config or not self.rag_config.enabled or not self.rag_engine:
|
||||||
return
|
return
|
||||||
|
|
||||||
def _run():
|
def _run() -> Result[None]:
|
||||||
try:
|
try:
|
||||||
self._set_rag_status("indexing...")
|
self._set_rag_status("indexing...")
|
||||||
import concurrent.futures
|
import concurrent.futures
|
||||||
@@ -3102,8 +3115,16 @@ class AppController:
|
|||||||
self.rag_engine.delete_documents_by_path(stale_paths)
|
self.rag_engine.delete_documents_by_path(stale_paths)
|
||||||
|
|
||||||
self._set_rag_status("ready")
|
self._set_rag_status("ready")
|
||||||
except Exception as e:
|
return OK
|
||||||
|
except (OSError, IOError, ValueError, TypeError, KeyError, AttributeError, RuntimeError) as e:
|
||||||
|
logging.getLogger(__name__).debug("RAG indexing error: %s", e, extra={"source": "app_controller._do_rag_sync._run"})
|
||||||
self._set_rag_status(f"error: {e}")
|
self._set_rag_status(f"error: {e}")
|
||||||
|
return Result(data=None, errors=[ErrorInfo(
|
||||||
|
kind=ErrorKind.INTERNAL,
|
||||||
|
message=str(e),
|
||||||
|
source="app_controller._do_rag_sync._run",
|
||||||
|
original=e,
|
||||||
|
)])
|
||||||
|
|
||||||
self.submit_io(_run)
|
self.submit_io(_run)
|
||||||
|
|
||||||
@@ -3124,12 +3145,13 @@ class AppController:
|
|||||||
return
|
return
|
||||||
self.ai_status = "fetching models..."
|
self.ai_status = "fetching models..."
|
||||||
|
|
||||||
def do_fetch() -> None:
|
def do_fetch() -> Result[None]:
|
||||||
try:
|
try:
|
||||||
for p in ai_client.PROVIDERS:
|
for p in ai_client.PROVIDERS:
|
||||||
try:
|
try:
|
||||||
self.all_available_models[p] = ai_client.list_models(p)
|
self.all_available_models[p] = ai_client.list_models(p)
|
||||||
except Exception as e:
|
except (OSError, IOError, ValueError, TypeError, KeyError, AttributeError, RuntimeError) as e:
|
||||||
|
logging.getLogger(__name__).debug("list_models failed for %s: %s", p, e, extra={"source": "app_controller._fetch_models.do_fetch.per_provider"})
|
||||||
self.all_available_models[p] = []
|
self.all_available_models[p] = []
|
||||||
|
|
||||||
models_list = self.all_available_models.get(provider, [])
|
models_list = self.all_available_models.get(provider, [])
|
||||||
@@ -3139,9 +3161,17 @@ class AppController:
|
|||||||
ai_client.set_provider(self._current_provider, self.current_model)
|
ai_client.set_provider(self._current_provider, self.current_model)
|
||||||
if self.ai_status == "fetching models...":
|
if self.ai_status == "fetching models...":
|
||||||
self.ai_status = f"models loaded: {len(models_list)}"
|
self.ai_status = f"models loaded: {len(models_list)}"
|
||||||
except Exception as e:
|
return OK
|
||||||
|
except (OSError, IOError, ValueError, TypeError, KeyError, AttributeError, RuntimeError) as e:
|
||||||
|
logging.getLogger(__name__).debug("model fetch error: %s", e, extra={"source": "app_controller._fetch_models.do_fetch"})
|
||||||
if self.ai_status == "fetching models...":
|
if self.ai_status == "fetching models...":
|
||||||
self.ai_status = f"model fetch error: {e}"
|
self.ai_status = f"model fetch error: {e}"
|
||||||
|
return Result(data=None, errors=[ErrorInfo(
|
||||||
|
kind=ErrorKind.INTERNAL,
|
||||||
|
message=str(e),
|
||||||
|
source="app_controller._fetch_models.do_fetch",
|
||||||
|
original=e,
|
||||||
|
)])
|
||||||
self.submit_io(do_fetch)
|
self.submit_io(do_fetch)
|
||||||
|
|
||||||
def _apply_preset(self, name: str, scope: str) -> None:
|
def _apply_preset(self, name: str, scope: str) -> None:
|
||||||
@@ -4284,7 +4314,8 @@ class AppController:
|
|||||||
self.submit_io(engine.run, md_content=full_md)
|
self.submit_io(engine.run, md_content=full_md)
|
||||||
sys.stderr.write(f"[DEBUG] _start_track_logic: Engine thread spawned for {track_id}.\n")
|
sys.stderr.write(f"[DEBUG] _start_track_logic: Engine thread spawned for {track_id}.\n")
|
||||||
sys.stderr.flush()
|
sys.stderr.flush()
|
||||||
except Exception as e:
|
except (OSError, IOError, ValueError, TypeError, KeyError, AttributeError, RuntimeError) as e:
|
||||||
|
logging.getLogger(__name__).debug("track start error: %s", e, extra={"source": "app_controller._start_track_logic"})
|
||||||
self.ai_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}")
|
||||||
|
|
||||||
@@ -4396,7 +4427,8 @@ class AppController:
|
|||||||
lines = len(fd.readlines())
|
lines = len(fd.readlines())
|
||||||
total_lines += lines
|
total_lines += lines
|
||||||
summary.append(f"- {f.relative_to(base)}: {lines} lines")
|
summary.append(f"- {f.relative_to(base)}: {lines} lines")
|
||||||
except Exception:
|
except (OSError, IOError, UnicodeDecodeError) as e:
|
||||||
|
logging.getLogger(__name__).debug("conductor file read failed for %s: %s", f, e, extra={"source": "app_controller._cb_run_conductor_setup"})
|
||||||
summary.append(f"- {f.relative_to(base)}: Error reading")
|
summary.append(f"- {f.relative_to(base)}: Error reading")
|
||||||
summary.append(f"Total Line Count: {total_lines}")
|
summary.append(f"Total Line Count: {total_lines}")
|
||||||
tracks_dir = base / "tracks"
|
tracks_dir = base / "tracks"
|
||||||
@@ -4493,7 +4525,8 @@ class AppController:
|
|||||||
self.disc_entries.clear()
|
self.disc_entries.clear()
|
||||||
self._recalculate_session_usage()
|
self._recalculate_session_usage()
|
||||||
self.ai_status = f"Loaded track: {state.metadata.name}"
|
self.ai_status = f"Loaded track: {state.metadata.name}"
|
||||||
except Exception as e:
|
except (OSError, IOError, ValueError, TypeError, KeyError, AttributeError, tomllib.TOMLDecodeError) as e:
|
||||||
|
logging.getLogger(__name__).debug("load track failed: %s", e, extra={"source": "app_controller._cb_load_track"})
|
||||||
self.ai_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}")
|
||||||
|
|
||||||
@@ -4522,8 +4555,8 @@ class AppController:
|
|||||||
track.tickets = new_tickets
|
track.tickets = new_tickets
|
||||||
state = models.TrackState(metadata=track, tasks=list(new_tickets))
|
state = models.TrackState(metadata=track, tasks=list(new_tickets))
|
||||||
project_manager.save_track_state(track.id, state, self.active_project_root)
|
project_manager.save_track_state(track.id, state, self.active_project_root)
|
||||||
except Exception as e:
|
except (OSError, IOError, ValueError, TypeError, KeyError, AttributeError) as e:
|
||||||
import sys
|
logging.getLogger(__name__).debug("push MMA state failed: %s", e, extra={"source": "app_controller._push_mma_state_update"})
|
||||||
print(f"Error pushing MMA state: {e}", file=sys.stderr)
|
print(f"Error pushing MMA state: {e}", file=sys.stderr)
|
||||||
|
|
||||||
def _load_active_tickets(self) -> None:
|
def _load_active_tickets(self) -> None:
|
||||||
@@ -4551,7 +4584,8 @@ class AppController:
|
|||||||
"status": bead.status,
|
"status": bead.status,
|
||||||
"depends_on": [],
|
"depends_on": [],
|
||||||
})
|
})
|
||||||
except Exception as e:
|
except (OSError, IOError, ValueError, TypeError, KeyError, AttributeError) as e:
|
||||||
|
logging.getLogger(__name__).debug("load beads failed: %s", e, extra={"source": "app_controller._load_active_tickets.beads"})
|
||||||
print(f"Error loading beads: {e}")
|
print(f"Error loading beads: {e}")
|
||||||
|
|
||||||
#region: --- Config I/O (single source of truth) ---
|
#region: --- Config I/O (single source of truth) ---
|
||||||
|
|||||||
Reference in New Issue
Block a user