forked from Rockachopa/Timmy-time-dashboard
feat: code quality audit + autoresearch integration + infra hardening (#150)
This commit is contained in:
committed by
GitHub
parent
fd0ede0d51
commit
ae3bb1cc21
@@ -30,9 +30,11 @@ logger = logging.getLogger(__name__)
|
||||
# Data structures
|
||||
# ---------------------------------------------------------------------------
|
||||
|
||||
|
||||
@dataclass
|
||||
class AgenticStep:
|
||||
"""Result of a single step in the agentic loop."""
|
||||
|
||||
step_num: int
|
||||
description: str
|
||||
result: str
|
||||
@@ -43,6 +45,7 @@ class AgenticStep:
|
||||
@dataclass
|
||||
class AgenticResult:
|
||||
"""Final result of the entire agentic loop."""
|
||||
|
||||
task_id: str
|
||||
task: str
|
||||
summary: str
|
||||
@@ -55,6 +58,7 @@ class AgenticResult:
|
||||
# Agent factory
|
||||
# ---------------------------------------------------------------------------
|
||||
|
||||
|
||||
def _get_loop_agent():
|
||||
"""Create a fresh agent for the agentic loop.
|
||||
|
||||
@@ -62,6 +66,7 @@ def _get_loop_agent():
|
||||
dedicated session so it doesn't pollute the main chat history.
|
||||
"""
|
||||
from timmy.agent import create_timmy
|
||||
|
||||
return create_timmy()
|
||||
|
||||
|
||||
@@ -85,6 +90,7 @@ def _parse_steps(plan_text: str) -> list[str]:
|
||||
# Core loop
|
||||
# ---------------------------------------------------------------------------
|
||||
|
||||
|
||||
async def run_agentic_loop(
|
||||
task: str,
|
||||
*,
|
||||
@@ -146,12 +152,15 @@ async def run_agentic_loop(
|
||||
was_truncated = planned_steps > total_steps
|
||||
|
||||
# Broadcast plan
|
||||
await _broadcast_progress("agentic.plan_ready", {
|
||||
"task_id": task_id,
|
||||
"task": task,
|
||||
"steps": steps,
|
||||
"total": total_steps,
|
||||
})
|
||||
await _broadcast_progress(
|
||||
"agentic.plan_ready",
|
||||
{
|
||||
"task_id": task_id,
|
||||
"task": task,
|
||||
"steps": steps,
|
||||
"total": total_steps,
|
||||
},
|
||||
)
|
||||
|
||||
# ── Phase 2: Execution ─────────────────────────────────────────────────
|
||||
completed_results: list[str] = []
|
||||
@@ -175,6 +184,7 @@ async def run_agentic_loop(
|
||||
|
||||
# Clean the response
|
||||
from timmy.session import _clean_response
|
||||
|
||||
step_result = _clean_response(step_result)
|
||||
|
||||
step = AgenticStep(
|
||||
@@ -188,13 +198,16 @@ async def run_agentic_loop(
|
||||
completed_results.append(f"Step {i}: {step_result[:200]}")
|
||||
|
||||
# Broadcast progress
|
||||
await _broadcast_progress("agentic.step_complete", {
|
||||
"task_id": task_id,
|
||||
"step": i,
|
||||
"total": total_steps,
|
||||
"description": step_desc,
|
||||
"result": step_result[:200],
|
||||
})
|
||||
await _broadcast_progress(
|
||||
"agentic.step_complete",
|
||||
{
|
||||
"task_id": task_id,
|
||||
"step": i,
|
||||
"total": total_steps,
|
||||
"description": step_desc,
|
||||
"result": step_result[:200],
|
||||
},
|
||||
)
|
||||
|
||||
if on_progress:
|
||||
await on_progress(step_desc, i, total_steps)
|
||||
@@ -210,11 +223,16 @@ async def run_agentic_loop(
|
||||
)
|
||||
try:
|
||||
adapt_run = await asyncio.to_thread(
|
||||
agent.run, adapt_prompt, stream=False,
|
||||
agent.run,
|
||||
adapt_prompt,
|
||||
stream=False,
|
||||
session_id=f"{session_id}_adapt{i}",
|
||||
)
|
||||
adapt_result = adapt_run.content if hasattr(adapt_run, "content") else str(adapt_run)
|
||||
adapt_result = (
|
||||
adapt_run.content if hasattr(adapt_run, "content") else str(adapt_run)
|
||||
)
|
||||
from timmy.session import _clean_response
|
||||
|
||||
adapt_result = _clean_response(adapt_result)
|
||||
|
||||
step = AgenticStep(
|
||||
@@ -227,14 +245,17 @@ async def run_agentic_loop(
|
||||
result.steps.append(step)
|
||||
completed_results.append(f"Step {i} (adapted): {adapt_result[:200]}")
|
||||
|
||||
await _broadcast_progress("agentic.step_adapted", {
|
||||
"task_id": task_id,
|
||||
"step": i,
|
||||
"total": total_steps,
|
||||
"description": step_desc,
|
||||
"error": str(exc),
|
||||
"adaptation": adapt_result[:200],
|
||||
})
|
||||
await _broadcast_progress(
|
||||
"agentic.step_adapted",
|
||||
{
|
||||
"task_id": task_id,
|
||||
"step": i,
|
||||
"total": total_steps,
|
||||
"description": step_desc,
|
||||
"error": str(exc),
|
||||
"adaptation": adapt_result[:200],
|
||||
},
|
||||
)
|
||||
|
||||
if on_progress:
|
||||
await on_progress(f"[Adapted] {step_desc}", i, total_steps)
|
||||
@@ -259,11 +280,16 @@ async def run_agentic_loop(
|
||||
)
|
||||
try:
|
||||
summary_run = await asyncio.to_thread(
|
||||
agent.run, summary_prompt, stream=False,
|
||||
agent.run,
|
||||
summary_prompt,
|
||||
stream=False,
|
||||
session_id=f"{session_id}_summary",
|
||||
)
|
||||
result.summary = summary_run.content if hasattr(summary_run, "content") else str(summary_run)
|
||||
result.summary = (
|
||||
summary_run.content if hasattr(summary_run, "content") else str(summary_run)
|
||||
)
|
||||
from timmy.session import _clean_response
|
||||
|
||||
result.summary = _clean_response(result.summary)
|
||||
except Exception as exc:
|
||||
logger.error("Agentic loop summary failed: %s", exc)
|
||||
@@ -281,13 +307,16 @@ async def run_agentic_loop(
|
||||
|
||||
result.total_duration_ms = int((time.monotonic() - start_time) * 1000)
|
||||
|
||||
await _broadcast_progress("agentic.task_complete", {
|
||||
"task_id": task_id,
|
||||
"status": result.status,
|
||||
"steps_completed": len(result.steps),
|
||||
"summary": result.summary[:300],
|
||||
"duration_ms": result.total_duration_ms,
|
||||
})
|
||||
await _broadcast_progress(
|
||||
"agentic.task_complete",
|
||||
{
|
||||
"task_id": task_id,
|
||||
"status": result.status,
|
||||
"steps_completed": len(result.steps),
|
||||
"summary": result.summary[:300],
|
||||
"duration_ms": result.total_duration_ms,
|
||||
},
|
||||
)
|
||||
|
||||
return result
|
||||
|
||||
@@ -296,10 +325,12 @@ async def run_agentic_loop(
|
||||
# WebSocket broadcast helper
|
||||
# ---------------------------------------------------------------------------
|
||||
|
||||
|
||||
async def _broadcast_progress(event: str, data: dict) -> None:
|
||||
"""Broadcast agentic loop progress via WebSocket (best-effort)."""
|
||||
try:
|
||||
from infrastructure.ws_manager.handler import ws_manager
|
||||
|
||||
await ws_manager.broadcast(event, data)
|
||||
except Exception:
|
||||
logger.debug("Agentic loop: WS broadcast failed for %s", event)
|
||||
|
||||
Reference in New Issue
Block a user