diff --git a/src/timmy/thinking.py b/src/timmy/thinking.py index 0b0850d..c05aeff 100644 --- a/src/timmy/thinking.py +++ b/src/timmy/thinking.py @@ -772,23 +772,10 @@ class ThinkingEngine: except Exception as exc: logger.debug("Thought issue filing skipped: %s", exc) - def _gather_system_snapshot(self) -> str: - """Gather lightweight real system state for grounding thoughts in reality. + # ── System snapshot helpers ──────────────────────────────────────────── - Returns a short multi-line string with current time, thought count, - recent chat activity, and task queue status. Never crashes — every - section is independently try/excepted. - """ - parts: list[str] = [] - - # Current local time - now = datetime.now().astimezone() - tz = now.strftime("%Z") or "UTC" - parts.append( - f"Local time: {now.strftime('%I:%M %p').lstrip('0')} {tz}, {now.strftime('%A %B %d')}" - ) - - # Thought count today (cheap DB query) + def _snap_thought_count(self, now: datetime) -> str | None: + """Return today's thought count, or *None* on failure.""" try: today_start = now.replace(hour=0, minute=0, second=0, microsecond=0) with _get_conn(self._db_path) as conn: @@ -796,66 +783,94 @@ class ThinkingEngine: "SELECT COUNT(*) as c FROM thoughts WHERE created_at >= ?", (today_start.isoformat(),), ).fetchone()["c"] - parts.append(f"Thoughts today: {count}") + return f"Thoughts today: {count}" except Exception as exc: logger.debug("Thought count query failed: %s", exc) - pass + return None - # Recent chat activity (in-memory, no I/O) + def _snap_chat_activity(self) -> list[str]: + """Return chat-activity lines (in-memory, no I/O).""" try: from infrastructure.chat_store import message_log messages = message_log.all() if messages: - parts.append(f"Chat messages this session: {len(messages)}") last = messages[-1] - parts.append(f'Last chat ({last.role}): "{last.content[:80]}"') - else: - parts.append("No chat messages this session") + return [ + f"Chat messages this session: {len(messages)}", + f'Last chat ({last.role}): "{last.content[:80]}"', + ] + return ["No chat messages this session"] except Exception as exc: logger.debug("Chat activity query failed: %s", exc) - pass + return [] - # Task queue (lightweight DB query) + def _snap_task_queue(self) -> str | None: + """Return a one-line task queue summary, or *None*.""" try: from swarm.task_queue.models import get_task_summary_for_briefing - summary = get_task_summary_for_briefing() - running = summary.get("running", 0) - pending = summary.get("pending_approval", 0) - done = summary.get("completed", 0) - failed = summary.get("failed", 0) + s = get_task_summary_for_briefing() + running, pending = s.get("running", 0), s.get("pending_approval", 0) + done, failed = s.get("completed", 0), s.get("failed", 0) if running or pending or done or failed: - parts.append( + return ( f"Tasks: {running} running, {pending} pending, " f"{done} completed, {failed} failed" ) except Exception as exc: logger.debug("Task queue query failed: %s", exc) - pass + return None - # Workspace updates (file-based communication with Hermes) + def _snap_workspace(self) -> list[str]: + """Return workspace-update lines (file-based Hermes comms).""" try: from timmy.workspace import workspace_monitor updates = workspace_monitor.get_pending_updates() + lines: list[str] = [] new_corr = updates.get("new_correspondence") - new_inbox = updates.get("new_inbox_files", []) - if new_corr: - # Count entries (assuming each entry starts with a timestamp or header) - line_count = len([line for line in new_corr.splitlines() if line.strip()]) - parts.append( + line_count = len([ln for ln in new_corr.splitlines() if ln.strip()]) + lines.append( f"Workspace: {line_count} new correspondence entries (latest from: Hermes)" ) + new_inbox = updates.get("new_inbox_files", []) if new_inbox: files_str = ", ".join(new_inbox[:5]) if len(new_inbox) > 5: files_str += f", ... (+{len(new_inbox) - 5} more)" - parts.append(f"Workspace: {len(new_inbox)} new inbox files: {files_str}") + lines.append(f"Workspace: {len(new_inbox)} new inbox files: {files_str}") + return lines except Exception as exc: logger.debug("Workspace check failed: %s", exc) - pass + return [] + + def _gather_system_snapshot(self) -> str: + """Gather lightweight real system state for grounding thoughts in reality. + + Returns a short multi-line string with current time, thought count, + recent chat activity, and task queue status. Never crashes — every + section is independently try/excepted. + """ + now = datetime.now().astimezone() + tz = now.strftime("%Z") or "UTC" + + parts: list[str] = [ + f"Local time: {now.strftime('%I:%M %p').lstrip('0')} {tz}, {now.strftime('%A %B %d')}" + ] + + thought_line = self._snap_thought_count(now) + if thought_line: + parts.append(thought_line) + + parts.extend(self._snap_chat_activity()) + + task_line = self._snap_task_queue() + if task_line: + parts.append(task_line) + + parts.extend(self._snap_workspace()) return "\n".join(parts) if parts else ""