diff --git a/backend/packages/harness/deerflow/agents/lead_agent/prompt.py b/backend/packages/harness/deerflow/agents/lead_agent/prompt.py index e1eaf69..add4374 100644 --- a/backend/packages/harness/deerflow/agents/lead_agent/prompt.py +++ b/backend/packages/harness/deerflow/agents/lead_agent/prompt.py @@ -1,8 +1,11 @@ +import logging from datetime import datetime from deerflow.config.agents_config import load_agent_soul from deerflow.skills import load_skills +logger = logging.getLogger(__name__) + def _build_subagent_section(max_concurrent: int) -> str: """Build the subagent system prompt section with dynamic concurrency limit. @@ -364,7 +367,7 @@ def _get_memory_context(agent_name: str | None = None) -> str: """ except Exception as e: - print(f"Failed to load memory context: {e}") + logger.error("Failed to load memory context: %s", e) return "" diff --git a/backend/packages/harness/deerflow/agents/memory/queue.py b/backend/packages/harness/deerflow/agents/memory/queue.py index 4184a52..a9a6838 100644 --- a/backend/packages/harness/deerflow/agents/memory/queue.py +++ b/backend/packages/harness/deerflow/agents/memory/queue.py @@ -1,5 +1,6 @@ """Memory update queue with debounce mechanism.""" +import logging import threading import time from dataclasses import dataclass, field @@ -8,6 +9,8 @@ from typing import Any from deerflow.config.memory_config import get_memory_config +logger = logging.getLogger(__name__) + @dataclass class ConversationContext: @@ -61,7 +64,7 @@ class MemoryUpdateQueue: # Reset or start the debounce timer self._reset_timer() - print(f"Memory update queued for thread {thread_id}, queue size: {len(self._queue)}") + logger.info("Memory update queued for thread %s, queue size: %d", thread_id, len(self._queue)) def _reset_timer(self) -> None: """Reset the debounce timer.""" @@ -79,7 +82,7 @@ class MemoryUpdateQueue: self._timer.daemon = True self._timer.start() - print(f"Memory update timer set for {config.debounce_seconds}s") + logger.debug("Memory update timer set for %ss", config.debounce_seconds) def _process_queue(self) -> None: """Process all queued conversation contexts.""" @@ -100,25 +103,25 @@ class MemoryUpdateQueue: self._queue.clear() self._timer = None - print(f"Processing {len(contexts_to_process)} queued memory updates") + logger.info("Processing %d queued memory updates", len(contexts_to_process)) try: updater = MemoryUpdater() for context in contexts_to_process: try: - print(f"Updating memory for thread {context.thread_id}") + logger.info("Updating memory for thread %s", context.thread_id) success = updater.update_memory( messages=context.messages, thread_id=context.thread_id, agent_name=context.agent_name, ) if success: - print(f"Memory updated successfully for thread {context.thread_id}") + logger.info("Memory updated successfully for thread %s", context.thread_id) else: - print(f"Memory update skipped/failed for thread {context.thread_id}") + logger.warning("Memory update skipped/failed for thread %s", context.thread_id) except Exception as e: - print(f"Error updating memory for thread {context.thread_id}: {e}") + logger.error("Error updating memory for thread %s: %s", context.thread_id, e) # Small delay between updates to avoid rate limiting if len(contexts_to_process) > 1: diff --git a/backend/packages/harness/deerflow/agents/middlewares/clarification_middleware.py b/backend/packages/harness/deerflow/agents/middlewares/clarification_middleware.py index d29987d..5074d8d 100644 --- a/backend/packages/harness/deerflow/agents/middlewares/clarification_middleware.py +++ b/backend/packages/harness/deerflow/agents/middlewares/clarification_middleware.py @@ -1,5 +1,6 @@ """Middleware for intercepting clarification requests and presenting them to the user.""" +import logging from collections.abc import Callable from typing import override @@ -10,6 +11,8 @@ from langgraph.graph import END from langgraph.prebuilt.tool_node import ToolCallRequest from langgraph.types import Command +logger = logging.getLogger(__name__) + class ClarificationMiddlewareState(AgentState): """Compatible with the `ThreadState` schema.""" @@ -101,8 +104,8 @@ class ClarificationMiddleware(AgentMiddleware[ClarificationMiddlewareState]): args = request.tool_call.get("args", {}) question = args.get("question", "") - print("[ClarificationMiddleware] Intercepted clarification request") - print(f"[ClarificationMiddleware] Question: {question}") + logger.info("Intercepted clarification request") + logger.debug("Clarification question: %s", question) # Format the clarification message formatted_message = self._format_clarification_message(args) diff --git a/backend/packages/harness/deerflow/agents/middlewares/memory_middleware.py b/backend/packages/harness/deerflow/agents/middlewares/memory_middleware.py index 7dc01d1..31d339f 100644 --- a/backend/packages/harness/deerflow/agents/middlewares/memory_middleware.py +++ b/backend/packages/harness/deerflow/agents/middlewares/memory_middleware.py @@ -1,5 +1,6 @@ """Middleware for memory mechanism.""" +import logging import re from typing import Any, override @@ -10,6 +11,8 @@ from langgraph.runtime import Runtime from deerflow.agents.memory.queue import get_memory_queue from deerflow.config.memory_config import get_memory_config +logger = logging.getLogger(__name__) + class MemoryMiddlewareState(AgentState): """Compatible with the `ThreadState` schema.""" @@ -122,13 +125,13 @@ class MemoryMiddleware(AgentMiddleware[MemoryMiddlewareState]): # Get thread ID from runtime context thread_id = runtime.context.get("thread_id") if runtime.context else None if not thread_id: - print("MemoryMiddleware: No thread_id in context, skipping memory update") + logger.debug("No thread_id in context, skipping memory update") return None # Get messages from state messages = state.get("messages", []) if not messages: - print("MemoryMiddleware: No messages in state, skipping memory update") + logger.debug("No messages in state, skipping memory update") return None # Filter to only keep user inputs and final assistant responses diff --git a/backend/packages/harness/deerflow/agents/middlewares/thread_data_middleware.py b/backend/packages/harness/deerflow/agents/middlewares/thread_data_middleware.py index 948085b..c25531e 100644 --- a/backend/packages/harness/deerflow/agents/middlewares/thread_data_middleware.py +++ b/backend/packages/harness/deerflow/agents/middlewares/thread_data_middleware.py @@ -1,3 +1,4 @@ +import logging from typing import NotRequired, override from langchain.agents import AgentState @@ -8,6 +9,8 @@ from langgraph.runtime import Runtime from deerflow.agents.thread_state import ThreadDataState from deerflow.config.paths import Paths, get_paths +logger = logging.getLogger(__name__) + class ThreadDataMiddlewareState(AgentState): """Compatible with the `ThreadState` schema.""" @@ -87,7 +90,7 @@ class ThreadDataMiddleware(AgentMiddleware[ThreadDataMiddlewareState]): else: # Eager initialization: create directories immediately paths = self._create_thread_directories(thread_id) - print(f"Created thread data directories for thread {thread_id}") + logger.debug("Created thread data directories for thread %s", thread_id) return { "thread_data": { diff --git a/backend/packages/harness/deerflow/agents/middlewares/view_image_middleware.py b/backend/packages/harness/deerflow/agents/middlewares/view_image_middleware.py index 29b3871..2870624 100644 --- a/backend/packages/harness/deerflow/agents/middlewares/view_image_middleware.py +++ b/backend/packages/harness/deerflow/agents/middlewares/view_image_middleware.py @@ -1,5 +1,6 @@ """Middleware for injecting image details into conversation before LLM call.""" +import logging from typing import NotRequired, override from langchain.agents import AgentState @@ -9,6 +10,8 @@ from langgraph.runtime import Runtime from deerflow.agents.thread_state import ViewedImageData +logger = logging.getLogger(__name__) + class ViewImageMiddlewareState(AgentState): """Compatible with the `ThreadState` schema.""" @@ -182,7 +185,7 @@ class ViewImageMiddleware(AgentMiddleware[ViewImageMiddlewareState]): # Create a new human message with mixed content (text + images) human_msg = HumanMessage(content=image_content) - print("[ViewImageMiddleware] Injecting image details message with images before LLM call") + logger.debug("Injecting image details message with images before LLM call") # Return state update with the new message return {"messages": [human_msg]} diff --git a/backend/packages/harness/deerflow/skills/loader.py b/backend/packages/harness/deerflow/skills/loader.py index 50c68d3..b596d62 100644 --- a/backend/packages/harness/deerflow/skills/loader.py +++ b/backend/packages/harness/deerflow/skills/loader.py @@ -1,9 +1,12 @@ +import logging import os from pathlib import Path from .parser import parse_skill_file from .types import Skill +logger = logging.getLogger(__name__) + def get_skills_root_path() -> Path: """ @@ -86,7 +89,7 @@ def load_skills(skills_path: Path | None = None, use_config: bool = True, enable skill.enabled = extensions_config.is_skill_enabled(skill.name, skill.category) except Exception as e: # If config loading fails, default to all enabled - print(f"Warning: Failed to load extensions config: {e}") + logger.warning("Failed to load extensions config: %s", e) # Filter by enabled status if requested if enabled_only: diff --git a/backend/packages/harness/deerflow/skills/parser.py b/backend/packages/harness/deerflow/skills/parser.py index fe1c04c..b7cb897 100644 --- a/backend/packages/harness/deerflow/skills/parser.py +++ b/backend/packages/harness/deerflow/skills/parser.py @@ -1,8 +1,11 @@ +import logging import re from pathlib import Path from .types import Skill +logger = logging.getLogger(__name__) + def parse_skill_file(skill_file: Path, category: str, relative_path: Path | None = None) -> Skill | None: """ @@ -61,5 +64,5 @@ def parse_skill_file(skill_file: Path, category: str, relative_path: Path | None ) except Exception as e: - print(f"Error parsing skill file {skill_file}: {e}") + logger.error("Error parsing skill file %s: %s", skill_file, e) return None