From bea27491589261d26ddd47cfdc5ff0559ac886ab Mon Sep 17 00:00:00 2001 From: hermes Date: Sun, 15 Mar 2026 11:48:54 -0400 Subject: [PATCH] =?UTF-8?q?[loop-cycle-49]=20refactor:=20narrow=20broad=20?= =?UTF-8?q?except=20Exception=20catches=20=E2=80=94=20batch=201=20(#158)?= =?UTF-8?q?=20(#178)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/config.py | 2 +- src/timmy/agentic_loop.py | 8 ++++---- src/timmy/interview.py | 2 +- src/timmy/memory/vector_store.py | 2 +- src/timmy/memory_system.py | 4 ++-- src/timmy/tools.py | 16 ++++++++-------- src/timmy/voice_loop.py | 6 +++--- 7 files changed, 20 insertions(+), 20 deletions(-) diff --git a/src/config.py b/src/config.py index 3e11033..7ceac6e 100644 --- a/src/config.py +++ b/src/config.py @@ -398,7 +398,7 @@ def check_ollama_model_available(model_name: str) -> bool: model_name == m or model_name == m.split(":")[0] or m.startswith(model_name) for m in models ) - except Exception as exc: + except (OSError, ValueError) as exc: _startup_logger.debug("Ollama model check failed: %s", exc) return False diff --git a/src/timmy/agentic_loop.py b/src/timmy/agentic_loop.py index 16f6aa4..90f2124 100644 --- a/src/timmy/agentic_loop.py +++ b/src/timmy/agentic_loop.py @@ -136,7 +136,7 @@ async def run_agentic_loop( agent.run, plan_prompt, stream=False, session_id=f"{session_id}_plan" ) plan_text = plan_run.content if hasattr(plan_run, "content") else str(plan_run) - except Exception as exc: + except Exception as exc: # broad catch intentional: agent.run can raise any error logger.error("Agentic loop: planning failed: %s", exc) result.status = "failed" result.summary = f"Planning failed: {exc}" @@ -217,7 +217,7 @@ async def run_agentic_loop( if on_progress: await on_progress(step_desc, i, total_steps) - except Exception as exc: + except Exception as exc: # broad catch intentional: agent.run can raise any error logger.warning("Agentic loop step %d failed: %s", i, exc) # ── Adaptation: ask model to adapt ───────────────────────────── @@ -265,7 +265,7 @@ async def run_agentic_loop( if on_progress: await on_progress(f"[Adapted] {step_desc}", i, total_steps) - except Exception as adapt_exc: + except Exception as adapt_exc: # broad catch intentional: agent.run can raise any error logger.error("Agentic loop adaptation also failed: %s", adapt_exc) step = AgenticStep( step_num=i, @@ -325,6 +325,6 @@ async def _broadcast_progress(event: str, data: dict) -> None: from infrastructure.ws_manager.handler import ws_manager await ws_manager.broadcast(event, data) - except Exception as exc: + except (ImportError, AttributeError, ConnectionError, RuntimeError) as exc: logger.warning("Agentic loop broadcast failed: %s", exc) logger.debug("Agentic loop: WS broadcast failed for %s", event) diff --git a/src/timmy/interview.py b/src/timmy/interview.py index 579ed15..5ff28da 100644 --- a/src/timmy/interview.py +++ b/src/timmy/interview.py @@ -86,7 +86,7 @@ def run_interview( try: answer = chat_fn(question) - except Exception as exc: + except Exception as exc: # broad catch intentional: chat_fn can raise any error logger.error("Interview question failed: %s", exc) answer = f"(Error: {exc})" diff --git a/src/timmy/memory/vector_store.py b/src/timmy/memory/vector_store.py index 37f951c..2c80290 100644 --- a/src/timmy/memory/vector_store.py +++ b/src/timmy/memory/vector_store.py @@ -21,7 +21,7 @@ def _check_embedding_model() -> bool | None: model = _get_embedding_model() return model is not None and model is not False - except Exception as exc: + except (ImportError, AttributeError) as exc: logger.debug("Embedding model check failed: %s", exc) return None diff --git a/src/timmy/memory_system.py b/src/timmy/memory_system.py index 3e31410..5dea81b 100644 --- a/src/timmy/memory_system.py +++ b/src/timmy/memory_system.py @@ -448,7 +448,7 @@ class MemorySystem: try: if SOUL_PATH.exists(): return SOUL_PATH.read_text() - except Exception as exc: + except OSError as exc: logger.debug("Failed to read soul.md: %s", exc) return "" @@ -503,7 +503,7 @@ class MemorySystem: for fact in facts: lines.append(f"- {fact[:200]}") return "\n".join(lines) - except Exception as exc: + except (ImportError, AttributeError) as exc: logger.debug("Failed to load known facts: %s", exc) return "" diff --git a/src/timmy/tools.py b/src/timmy/tools.py index 3fe1ef2..bf992e1 100644 --- a/src/timmy/tools.py +++ b/src/timmy/tools.py @@ -182,7 +182,7 @@ def calculator(expression: str) -> str: tree = ast.parse(expression, mode="eval") result = _safe_eval(tree, allowed_names) return str(result) - except Exception as e: + except Exception as e: # broad catch intentional: arbitrary code execution return f"Error evaluating '{expression}': {e}" @@ -318,7 +318,7 @@ def create_aider_tool(base_path: Path): return "Error: Aider not installed. Run: pip install aider" except subprocess.TimeoutExpired: return "Error: Aider timed out after 120 seconds" - except Exception as e: + except (OSError, subprocess.SubprocessError) as e: return f"Error running Aider: {str(e)}" return AiderTool(base_path) @@ -445,7 +445,7 @@ def consult_grok(query: str) -> str: tool_name="consult_grok", success=True, ) - except Exception as exc: + except (ImportError, AttributeError) as exc: logger.warning("Tool execution failed (consult_grok logging): %s", exc) pass @@ -459,7 +459,7 @@ def consult_grok(query: str) -> str: sats = min(settings.grok_max_sats_per_query, 100) inv = ln.create_invoice(sats, f"Grok query: {query[:50]}") invoice_info = f"\n[Lightning invoice: {sats} sats — {inv.payment_request[:40]}...]" - except Exception as exc: + except (ImportError, OSError, ValueError) as exc: logger.warning("Tool execution failed (Lightning invoice): %s", exc) pass @@ -500,7 +500,7 @@ def _register_grok_tool(toolkit: Toolkit) -> None: if grok_available(): toolkit.register(consult_grok, name="consult_grok") logger.info("Grok consultation tool registered") - except Exception as exc: + except (ImportError, AttributeError) as exc: logger.warning("Tool execution failed (Grok registration): %s", exc) logger.debug("Grok tool not available") @@ -514,7 +514,7 @@ def _register_memory_tools(toolkit: Toolkit) -> None: toolkit.register(memory_write, name="memory_write") toolkit.register(memory_read, name="memory_read") toolkit.register(memory_forget, name="memory_forget") - except Exception as exc: + except (ImportError, AttributeError) as exc: logger.warning("Tool execution failed (Memory tools registration): %s", exc) logger.debug("Memory tools not available") @@ -563,7 +563,7 @@ def _register_agentic_loop_tool(toolkit: Toolkit) -> None: ) toolkit.register(plan_and_execute, name="plan_and_execute") - except Exception as exc: + except (ImportError, AttributeError) as exc: logger.warning("Tool execution failed (plan_and_execute registration): %s", exc) logger.debug("plan_and_execute tool not available") @@ -582,7 +582,7 @@ def _register_introspection_tools(toolkit: Toolkit) -> None: toolkit.register(check_ollama_health, name="check_ollama_health") toolkit.register(get_memory_status, name="get_memory_status") toolkit.register(run_self_tests, name="run_self_tests") - except Exception as exc: + except (ImportError, AttributeError) as exc: logger.warning("Tool execution failed (Introspection tools registration): %s", exc) logger.debug("Introspection tools not available") diff --git a/src/timmy/voice_loop.py b/src/timmy/voice_loop.py index 8375fca..24e632b 100644 --- a/src/timmy/voice_loop.py +++ b/src/timmy/voice_loop.py @@ -345,7 +345,7 @@ class VoiceLoop: try: loop = self._get_loop() response = loop.run_until_complete(self._chat(user_text)) - except Exception as exc: + except (ConnectionError, RuntimeError, ValueError) as exc: logger.error("Timmy chat failed: %s", exc) response = "I'm having trouble thinking right now. Could you try again?" @@ -465,7 +465,7 @@ class VoiceLoop: try: self._loop.run_until_complete(self._loop.shutdown_asyncgens()) - except Exception as exc: + except RuntimeError as exc: logger.debug("Shutdown asyncgens failed: %s", exc) pass @@ -473,7 +473,7 @@ class VoiceLoop: warnings.simplefilter("ignore", RuntimeWarning) try: self._loop.close() - except Exception as exc: + except RuntimeError as exc: logger.debug("Loop close failed: %s", exc) pass