refactor: consolidate debug logging across tools with shared DebugSession class
- Introduced a new DebugSession class in tools/debug_helpers.py to centralize debug logging functionality, replacing duplicated code across various tool modules. - Updated image_generation_tool.py, mixture_of_agents_tool.py, vision_tools.py, web_tools.py, and others to utilize the new DebugSession for logging tool calls and saving debug logs. - Enhanced maintainability and consistency in debug logging practices across the codebase.
This commit is contained in:
104
tools/debug_helpers.py
Normal file
104
tools/debug_helpers.py
Normal file
@@ -0,0 +1,104 @@
|
|||||||
|
"""Shared debug session infrastructure for Hermes tools.
|
||||||
|
|
||||||
|
Replaces the identical DEBUG_MODE / _log_debug_call / _save_debug_log /
|
||||||
|
get_debug_session_info boilerplate previously duplicated across web_tools,
|
||||||
|
vision_tools, mixture_of_agents_tool, and image_generation_tool.
|
||||||
|
|
||||||
|
Usage in a tool module:
|
||||||
|
|
||||||
|
from tools.debug_helpers import DebugSession
|
||||||
|
|
||||||
|
_debug = DebugSession("web_tools", env_var="WEB_TOOLS_DEBUG")
|
||||||
|
|
||||||
|
# Log a call (no-op when debug mode is off)
|
||||||
|
_debug.log_call("web_search", {"query": q, "results": len(r)})
|
||||||
|
|
||||||
|
# Save the debug log (no-op when debug mode is off)
|
||||||
|
_debug.save()
|
||||||
|
|
||||||
|
# Expose debug info to external callers
|
||||||
|
def get_debug_session_info():
|
||||||
|
return _debug.get_session_info()
|
||||||
|
"""
|
||||||
|
|
||||||
|
import datetime
|
||||||
|
import json
|
||||||
|
import logging
|
||||||
|
import os
|
||||||
|
import uuid
|
||||||
|
from pathlib import Path
|
||||||
|
from typing import Any, Dict
|
||||||
|
|
||||||
|
logger = logging.getLogger(__name__)
|
||||||
|
|
||||||
|
|
||||||
|
class DebugSession:
|
||||||
|
"""Per-tool debug session that records tool calls to a JSON log file.
|
||||||
|
|
||||||
|
Activated by a tool-specific environment variable (e.g. WEB_TOOLS_DEBUG=true).
|
||||||
|
When disabled, all methods are cheap no-ops.
|
||||||
|
"""
|
||||||
|
|
||||||
|
def __init__(self, tool_name: str, *, env_var: str) -> None:
|
||||||
|
self.tool_name = tool_name
|
||||||
|
self.enabled = os.getenv(env_var, "false").lower() == "true"
|
||||||
|
self.session_id = str(uuid.uuid4()) if self.enabled else ""
|
||||||
|
self.log_dir = Path("./logs")
|
||||||
|
self._calls: list[Dict[str, Any]] = []
|
||||||
|
self._start_time = datetime.datetime.now().isoformat() if self.enabled else ""
|
||||||
|
|
||||||
|
if self.enabled:
|
||||||
|
self.log_dir.mkdir(exist_ok=True)
|
||||||
|
logger.debug("%s debug mode enabled - Session ID: %s",
|
||||||
|
tool_name, self.session_id)
|
||||||
|
|
||||||
|
@property
|
||||||
|
def active(self) -> bool:
|
||||||
|
return self.enabled
|
||||||
|
|
||||||
|
def log_call(self, call_name: str, call_data: Dict[str, Any]) -> None:
|
||||||
|
"""Append a tool-call entry to the in-memory log."""
|
||||||
|
if not self.enabled:
|
||||||
|
return
|
||||||
|
self._calls.append({
|
||||||
|
"timestamp": datetime.datetime.now().isoformat(),
|
||||||
|
"tool_name": call_name,
|
||||||
|
**call_data,
|
||||||
|
})
|
||||||
|
|
||||||
|
def save(self) -> None:
|
||||||
|
"""Flush the in-memory log to a JSON file in the logs directory."""
|
||||||
|
if not self.enabled:
|
||||||
|
return
|
||||||
|
try:
|
||||||
|
filename = f"{self.tool_name}_debug_{self.session_id}.json"
|
||||||
|
filepath = self.log_dir / filename
|
||||||
|
payload = {
|
||||||
|
"session_id": self.session_id,
|
||||||
|
"start_time": self._start_time,
|
||||||
|
"end_time": datetime.datetime.now().isoformat(),
|
||||||
|
"debug_enabled": True,
|
||||||
|
"total_calls": len(self._calls),
|
||||||
|
"tool_calls": self._calls,
|
||||||
|
}
|
||||||
|
with open(filepath, "w", encoding="utf-8") as f:
|
||||||
|
json.dump(payload, f, indent=2, ensure_ascii=False)
|
||||||
|
logger.debug("%s debug log saved: %s", self.tool_name, filepath)
|
||||||
|
except Exception as e:
|
||||||
|
logger.error("Error saving %s debug log: %s", self.tool_name, e)
|
||||||
|
|
||||||
|
def get_session_info(self) -> Dict[str, Any]:
|
||||||
|
"""Return a summary dict suitable for returning from get_debug_session_info()."""
|
||||||
|
if not self.enabled:
|
||||||
|
return {
|
||||||
|
"enabled": False,
|
||||||
|
"session_id": None,
|
||||||
|
"log_path": None,
|
||||||
|
"total_calls": 0,
|
||||||
|
}
|
||||||
|
return {
|
||||||
|
"enabled": True,
|
||||||
|
"session_id": self.session_id,
|
||||||
|
"log_path": str(self.log_dir / f"{self.tool_name}_debug_{self.session_id}.json"),
|
||||||
|
"total_calls": len(self._calls),
|
||||||
|
}
|
||||||
@@ -32,11 +32,10 @@ import json
|
|||||||
import logging
|
import logging
|
||||||
import os
|
import os
|
||||||
import asyncio
|
import asyncio
|
||||||
import uuid
|
|
||||||
import datetime
|
import datetime
|
||||||
from pathlib import Path
|
|
||||||
from typing import Dict, Any, Optional, Union
|
from typing import Dict, Any, Optional, Union
|
||||||
import fal_client
|
import fal_client
|
||||||
|
from tools.debug_helpers import DebugSession
|
||||||
|
|
||||||
logger = logging.getLogger(__name__)
|
logger = logging.getLogger(__name__)
|
||||||
|
|
||||||
@@ -78,65 +77,7 @@ VALID_IMAGE_SIZES = [
|
|||||||
VALID_OUTPUT_FORMATS = ["jpeg", "png"]
|
VALID_OUTPUT_FORMATS = ["jpeg", "png"]
|
||||||
VALID_ACCELERATION_MODES = ["none", "regular", "high"]
|
VALID_ACCELERATION_MODES = ["none", "regular", "high"]
|
||||||
|
|
||||||
# Debug mode configuration
|
_debug = DebugSession("image_tools", env_var="IMAGE_TOOLS_DEBUG")
|
||||||
DEBUG_MODE = os.getenv("IMAGE_TOOLS_DEBUG", "false").lower() == "true"
|
|
||||||
DEBUG_SESSION_ID = str(uuid.uuid4())
|
|
||||||
DEBUG_LOG_PATH = Path("./logs")
|
|
||||||
DEBUG_DATA = {
|
|
||||||
"session_id": DEBUG_SESSION_ID,
|
|
||||||
"start_time": datetime.datetime.now().isoformat(),
|
|
||||||
"debug_enabled": DEBUG_MODE,
|
|
||||||
"tool_calls": []
|
|
||||||
} if DEBUG_MODE else None
|
|
||||||
|
|
||||||
# Create logs directory if debug mode is enabled
|
|
||||||
if DEBUG_MODE:
|
|
||||||
DEBUG_LOG_PATH.mkdir(exist_ok=True)
|
|
||||||
logger.debug("Image generation debug mode enabled - Session ID: %s", DEBUG_SESSION_ID)
|
|
||||||
|
|
||||||
|
|
||||||
def _log_debug_call(tool_name: str, call_data: Dict[str, Any]) -> None:
|
|
||||||
"""
|
|
||||||
Log a debug call entry to the global debug data structure.
|
|
||||||
|
|
||||||
Args:
|
|
||||||
tool_name (str): Name of the tool being called
|
|
||||||
call_data (Dict[str, Any]): Data about the call including parameters and results
|
|
||||||
"""
|
|
||||||
if not DEBUG_MODE or not DEBUG_DATA:
|
|
||||||
return
|
|
||||||
|
|
||||||
call_entry = {
|
|
||||||
"timestamp": datetime.datetime.now().isoformat(),
|
|
||||||
"tool_name": tool_name,
|
|
||||||
**call_data
|
|
||||||
}
|
|
||||||
|
|
||||||
DEBUG_DATA["tool_calls"].append(call_entry)
|
|
||||||
|
|
||||||
|
|
||||||
def _save_debug_log() -> None:
|
|
||||||
"""
|
|
||||||
Save the current debug data to a JSON file in the logs directory.
|
|
||||||
"""
|
|
||||||
if not DEBUG_MODE or not DEBUG_DATA:
|
|
||||||
return
|
|
||||||
|
|
||||||
try:
|
|
||||||
debug_filename = f"image_tools_debug_{DEBUG_SESSION_ID}.json"
|
|
||||||
debug_filepath = DEBUG_LOG_PATH / debug_filename
|
|
||||||
|
|
||||||
# Update end time
|
|
||||||
DEBUG_DATA["end_time"] = datetime.datetime.now().isoformat()
|
|
||||||
DEBUG_DATA["total_calls"] = len(DEBUG_DATA["tool_calls"])
|
|
||||||
|
|
||||||
with open(debug_filepath, 'w', encoding='utf-8') as f:
|
|
||||||
json.dump(DEBUG_DATA, f, indent=2, ensure_ascii=False)
|
|
||||||
|
|
||||||
logger.debug("Image generation debug log saved: %s", debug_filepath)
|
|
||||||
|
|
||||||
except Exception as e:
|
|
||||||
logger.error("Error saving image generation debug log: %s", e)
|
|
||||||
|
|
||||||
|
|
||||||
def _validate_parameters(
|
def _validate_parameters(
|
||||||
@@ -423,8 +364,8 @@ async def image_generate_tool(
|
|||||||
debug_call_data["generation_time"] = generation_time
|
debug_call_data["generation_time"] = generation_time
|
||||||
|
|
||||||
# Log debug information
|
# Log debug information
|
||||||
_log_debug_call("image_generate_tool", debug_call_data)
|
_debug.log_call("image_generate_tool", debug_call_data)
|
||||||
_save_debug_log()
|
_debug.save()
|
||||||
|
|
||||||
return json.dumps(response_data, indent=2, ensure_ascii=False)
|
return json.dumps(response_data, indent=2, ensure_ascii=False)
|
||||||
|
|
||||||
@@ -441,8 +382,8 @@ async def image_generate_tool(
|
|||||||
|
|
||||||
debug_call_data["error"] = error_msg
|
debug_call_data["error"] = error_msg
|
||||||
debug_call_data["generation_time"] = generation_time
|
debug_call_data["generation_time"] = generation_time
|
||||||
_log_debug_call("image_generate_tool", debug_call_data)
|
_debug.log_call("image_generate_tool", debug_call_data)
|
||||||
_save_debug_log()
|
_debug.save()
|
||||||
|
|
||||||
return json.dumps(response_data, indent=2, ensure_ascii=False)
|
return json.dumps(response_data, indent=2, ensure_ascii=False)
|
||||||
|
|
||||||
@@ -484,20 +425,7 @@ def get_debug_session_info() -> Dict[str, Any]:
|
|||||||
Returns:
|
Returns:
|
||||||
Dict[str, Any]: Dictionary containing debug session information
|
Dict[str, Any]: Dictionary containing debug session information
|
||||||
"""
|
"""
|
||||||
if not DEBUG_MODE or not DEBUG_DATA:
|
return _debug.get_session_info()
|
||||||
return {
|
|
||||||
"enabled": False,
|
|
||||||
"session_id": None,
|
|
||||||
"log_path": None,
|
|
||||||
"total_calls": 0
|
|
||||||
}
|
|
||||||
|
|
||||||
return {
|
|
||||||
"enabled": True,
|
|
||||||
"session_id": DEBUG_SESSION_ID,
|
|
||||||
"log_path": str(DEBUG_LOG_PATH / f"image_tools_debug_{DEBUG_SESSION_ID}.json"),
|
|
||||||
"total_calls": len(DEBUG_DATA["tool_calls"])
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
if __name__ == "__main__":
|
if __name__ == "__main__":
|
||||||
@@ -532,9 +460,9 @@ if __name__ == "__main__":
|
|||||||
print(f"🔍 Auto-upscaling with: {UPSCALER_MODEL} ({UPSCALER_FACTOR}x)")
|
print(f"🔍 Auto-upscaling with: {UPSCALER_MODEL} ({UPSCALER_FACTOR}x)")
|
||||||
|
|
||||||
# Show debug mode status
|
# Show debug mode status
|
||||||
if DEBUG_MODE:
|
if _debug.active:
|
||||||
print(f"🐛 Debug mode ENABLED - Session ID: {DEBUG_SESSION_ID}")
|
print(f"🐛 Debug mode ENABLED - Session ID: {_debug.session_id}")
|
||||||
print(f" Debug logs will be saved to: ./logs/image_tools_debug_{DEBUG_SESSION_ID}.json")
|
print(f" Debug logs will be saved to: ./logs/image_tools_debug_{_debug.session_id}.json")
|
||||||
else:
|
else:
|
||||||
print("🐛 Debug mode disabled (set IMAGE_TOOLS_DEBUG=true to enable)")
|
print("🐛 Debug mode disabled (set IMAGE_TOOLS_DEBUG=true to enable)")
|
||||||
|
|
||||||
|
|||||||
@@ -49,30 +49,13 @@ import json
|
|||||||
import logging
|
import logging
|
||||||
import os
|
import os
|
||||||
import asyncio
|
import asyncio
|
||||||
import uuid
|
|
||||||
import datetime
|
import datetime
|
||||||
from pathlib import Path
|
|
||||||
from typing import Dict, Any, List, Optional
|
from typing import Dict, Any, List, Optional
|
||||||
from openai import AsyncOpenAI
|
from tools.openrouter_client import get_async_client as _get_openrouter_client, check_api_key as check_openrouter_api_key
|
||||||
from hermes_constants import OPENROUTER_BASE_URL
|
from tools.debug_helpers import DebugSession
|
||||||
|
|
||||||
logger = logging.getLogger(__name__)
|
logger = logging.getLogger(__name__)
|
||||||
|
|
||||||
_openrouter_client = None
|
|
||||||
|
|
||||||
def _get_openrouter_client():
|
|
||||||
"""Get or create the OpenRouter client (lazy initialization)."""
|
|
||||||
global _openrouter_client
|
|
||||||
if _openrouter_client is None:
|
|
||||||
api_key = os.getenv("OPENROUTER_API_KEY")
|
|
||||||
if not api_key:
|
|
||||||
raise ValueError("OPENROUTER_API_KEY environment variable not set")
|
|
||||||
_openrouter_client = AsyncOpenAI(
|
|
||||||
api_key=api_key,
|
|
||||||
base_url=OPENROUTER_BASE_URL
|
|
||||||
)
|
|
||||||
return _openrouter_client
|
|
||||||
|
|
||||||
# Configuration for MoA processing
|
# Configuration for MoA processing
|
||||||
# Reference models - these generate diverse initial responses in parallel (OpenRouter slugs)
|
# Reference models - these generate diverse initial responses in parallel (OpenRouter slugs)
|
||||||
REFERENCE_MODELS = [
|
REFERENCE_MODELS = [
|
||||||
@@ -97,65 +80,7 @@ AGGREGATOR_SYSTEM_PROMPT = """You have been provided with a set of responses fro
|
|||||||
|
|
||||||
Responses from models:"""
|
Responses from models:"""
|
||||||
|
|
||||||
# Debug mode configuration
|
_debug = DebugSession("moa_tools", env_var="MOA_TOOLS_DEBUG")
|
||||||
DEBUG_MODE = os.getenv("MOA_TOOLS_DEBUG", "false").lower() == "true"
|
|
||||||
DEBUG_SESSION_ID = str(uuid.uuid4())
|
|
||||||
DEBUG_LOG_PATH = Path("./logs")
|
|
||||||
DEBUG_DATA = {
|
|
||||||
"session_id": DEBUG_SESSION_ID,
|
|
||||||
"start_time": datetime.datetime.now().isoformat(),
|
|
||||||
"debug_enabled": DEBUG_MODE,
|
|
||||||
"tool_calls": []
|
|
||||||
} if DEBUG_MODE else None
|
|
||||||
|
|
||||||
# Create logs directory if debug mode is enabled
|
|
||||||
if DEBUG_MODE:
|
|
||||||
DEBUG_LOG_PATH.mkdir(exist_ok=True)
|
|
||||||
logger.debug("MoA debug mode enabled - Session ID: %s", DEBUG_SESSION_ID)
|
|
||||||
|
|
||||||
|
|
||||||
def _log_debug_call(tool_name: str, call_data: Dict[str, Any]) -> None:
|
|
||||||
"""
|
|
||||||
Log a debug call entry to the global debug data structure.
|
|
||||||
|
|
||||||
Args:
|
|
||||||
tool_name (str): Name of the tool being called
|
|
||||||
call_data (Dict[str, Any]): Data about the call including parameters and results
|
|
||||||
"""
|
|
||||||
if not DEBUG_MODE or not DEBUG_DATA:
|
|
||||||
return
|
|
||||||
|
|
||||||
call_entry = {
|
|
||||||
"timestamp": datetime.datetime.now().isoformat(),
|
|
||||||
"tool_name": tool_name,
|
|
||||||
**call_data
|
|
||||||
}
|
|
||||||
|
|
||||||
DEBUG_DATA["tool_calls"].append(call_entry)
|
|
||||||
|
|
||||||
|
|
||||||
def _save_debug_log() -> None:
|
|
||||||
"""
|
|
||||||
Save the current debug data to a JSON file in the logs directory.
|
|
||||||
"""
|
|
||||||
if not DEBUG_MODE or not DEBUG_DATA:
|
|
||||||
return
|
|
||||||
|
|
||||||
try:
|
|
||||||
debug_filename = f"moa_tools_debug_{DEBUG_SESSION_ID}.json"
|
|
||||||
debug_filepath = DEBUG_LOG_PATH / debug_filename
|
|
||||||
|
|
||||||
# Update end time
|
|
||||||
DEBUG_DATA["end_time"] = datetime.datetime.now().isoformat()
|
|
||||||
DEBUG_DATA["total_calls"] = len(DEBUG_DATA["tool_calls"])
|
|
||||||
|
|
||||||
with open(debug_filepath, 'w', encoding='utf-8') as f:
|
|
||||||
json.dump(DEBUG_DATA, f, indent=2, ensure_ascii=False)
|
|
||||||
|
|
||||||
logger.debug("MoA debug log saved: %s", debug_filepath)
|
|
||||||
|
|
||||||
except Exception as e:
|
|
||||||
logger.error("Error saving MoA debug log: %s", e)
|
|
||||||
|
|
||||||
|
|
||||||
def _construct_aggregator_prompt(system_prompt: str, responses: List[str]) -> str:
|
def _construct_aggregator_prompt(system_prompt: str, responses: List[str]) -> str:
|
||||||
@@ -432,8 +357,8 @@ async def mixture_of_agents_tool(
|
|||||||
debug_call_data["models_used"] = result["models_used"]
|
debug_call_data["models_used"] = result["models_used"]
|
||||||
|
|
||||||
# Log debug information
|
# Log debug information
|
||||||
_log_debug_call("mixture_of_agents_tool", debug_call_data)
|
_debug.log_call("mixture_of_agents_tool", debug_call_data)
|
||||||
_save_debug_log()
|
_debug.save()
|
||||||
|
|
||||||
return json.dumps(result, indent=2, ensure_ascii=False)
|
return json.dumps(result, indent=2, ensure_ascii=False)
|
||||||
|
|
||||||
@@ -458,22 +383,12 @@ async def mixture_of_agents_tool(
|
|||||||
|
|
||||||
debug_call_data["error"] = error_msg
|
debug_call_data["error"] = error_msg
|
||||||
debug_call_data["processing_time_seconds"] = processing_time
|
debug_call_data["processing_time_seconds"] = processing_time
|
||||||
_log_debug_call("mixture_of_agents_tool", debug_call_data)
|
_debug.log_call("mixture_of_agents_tool", debug_call_data)
|
||||||
_save_debug_log()
|
_debug.save()
|
||||||
|
|
||||||
return json.dumps(result, indent=2, ensure_ascii=False)
|
return json.dumps(result, indent=2, ensure_ascii=False)
|
||||||
|
|
||||||
|
|
||||||
def check_openrouter_api_key() -> bool:
|
|
||||||
"""
|
|
||||||
Check if the OpenRouter API key is available in environment variables.
|
|
||||||
|
|
||||||
Returns:
|
|
||||||
bool: True if API key is set, False otherwise
|
|
||||||
"""
|
|
||||||
return bool(os.getenv("OPENROUTER_API_KEY"))
|
|
||||||
|
|
||||||
|
|
||||||
def check_moa_requirements() -> bool:
|
def check_moa_requirements() -> bool:
|
||||||
"""
|
"""
|
||||||
Check if all requirements for MoA tools are met.
|
Check if all requirements for MoA tools are met.
|
||||||
@@ -491,20 +406,7 @@ def get_debug_session_info() -> Dict[str, Any]:
|
|||||||
Returns:
|
Returns:
|
||||||
Dict[str, Any]: Dictionary containing debug session information
|
Dict[str, Any]: Dictionary containing debug session information
|
||||||
"""
|
"""
|
||||||
if not DEBUG_MODE or not DEBUG_DATA:
|
return _debug.get_session_info()
|
||||||
return {
|
|
||||||
"enabled": False,
|
|
||||||
"session_id": None,
|
|
||||||
"log_path": None,
|
|
||||||
"total_calls": 0
|
|
||||||
}
|
|
||||||
|
|
||||||
return {
|
|
||||||
"enabled": True,
|
|
||||||
"session_id": DEBUG_SESSION_ID,
|
|
||||||
"log_path": str(DEBUG_LOG_PATH / f"moa_tools_debug_{DEBUG_SESSION_ID}.json"),
|
|
||||||
"total_calls": len(DEBUG_DATA["tool_calls"])
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
def get_available_models() -> Dict[str, List[str]]:
|
def get_available_models() -> Dict[str, List[str]]:
|
||||||
@@ -570,9 +472,9 @@ if __name__ == "__main__":
|
|||||||
print(f" 📊 Minimum successful models: {config['min_successful_references']}")
|
print(f" 📊 Minimum successful models: {config['min_successful_references']}")
|
||||||
|
|
||||||
# Show debug mode status
|
# Show debug mode status
|
||||||
if DEBUG_MODE:
|
if _debug.active:
|
||||||
print(f"\n🐛 Debug mode ENABLED - Session ID: {DEBUG_SESSION_ID}")
|
print(f"\n🐛 Debug mode ENABLED - Session ID: {_debug.session_id}")
|
||||||
print(f" Debug logs will be saved to: ./logs/moa_tools_debug_{DEBUG_SESSION_ID}.json")
|
print(f" Debug logs will be saved to: ./logs/moa_tools_debug_{_debug.session_id}.json")
|
||||||
else:
|
else:
|
||||||
print("\n🐛 Debug mode disabled (set MOA_TOOLS_DEBUG=true to enable)")
|
print("\n🐛 Debug mode disabled (set MOA_TOOLS_DEBUG=true to enable)")
|
||||||
|
|
||||||
|
|||||||
34
tools/openrouter_client.py
Normal file
34
tools/openrouter_client.py
Normal file
@@ -0,0 +1,34 @@
|
|||||||
|
"""Shared OpenRouter API client for Hermes tools.
|
||||||
|
|
||||||
|
Provides a single lazy-initialized AsyncOpenAI client that all tool modules
|
||||||
|
can share, eliminating the duplicated _get_openrouter_client() /
|
||||||
|
_get_summarizer_client() pattern previously copy-pasted across web_tools,
|
||||||
|
vision_tools, mixture_of_agents_tool, and session_search_tool.
|
||||||
|
"""
|
||||||
|
|
||||||
|
import os
|
||||||
|
|
||||||
|
from openai import AsyncOpenAI
|
||||||
|
from hermes_constants import OPENROUTER_BASE_URL
|
||||||
|
|
||||||
|
_client: AsyncOpenAI | None = None
|
||||||
|
|
||||||
|
|
||||||
|
def get_async_client() -> AsyncOpenAI:
|
||||||
|
"""Return a shared AsyncOpenAI client pointed at OpenRouter.
|
||||||
|
|
||||||
|
The client is created lazily on first call and reused thereafter.
|
||||||
|
Raises ValueError if OPENROUTER_API_KEY is not set.
|
||||||
|
"""
|
||||||
|
global _client
|
||||||
|
if _client is None:
|
||||||
|
api_key = os.getenv("OPENROUTER_API_KEY")
|
||||||
|
if not api_key:
|
||||||
|
raise ValueError("OPENROUTER_API_KEY environment variable not set")
|
||||||
|
_client = AsyncOpenAI(api_key=api_key, base_url=OPENROUTER_BASE_URL)
|
||||||
|
return _client
|
||||||
|
|
||||||
|
|
||||||
|
def check_api_key() -> bool:
|
||||||
|
"""Check whether the OpenRouter API key is present."""
|
||||||
|
return bool(os.getenv("OPENROUTER_API_KEY"))
|
||||||
@@ -22,29 +22,12 @@ import os
|
|||||||
import logging
|
import logging
|
||||||
from typing import Dict, Any, List, Optional
|
from typing import Dict, Any, List, Optional
|
||||||
|
|
||||||
from openai import AsyncOpenAI
|
from tools.openrouter_client import get_async_client as _get_client
|
||||||
from hermes_constants import OPENROUTER_BASE_URL
|
|
||||||
|
|
||||||
SUMMARIZER_MODEL = "google/gemini-3-flash-preview"
|
SUMMARIZER_MODEL = "google/gemini-3-flash-preview"
|
||||||
MAX_SESSION_CHARS = 100_000
|
MAX_SESSION_CHARS = 100_000
|
||||||
MAX_SUMMARY_TOKENS = 2000
|
MAX_SUMMARY_TOKENS = 2000
|
||||||
|
|
||||||
_summarizer_client = None
|
|
||||||
|
|
||||||
|
|
||||||
def _get_client() -> AsyncOpenAI:
|
|
||||||
"""Lazy-init the summarizer client (shared with web_tools pattern)."""
|
|
||||||
global _summarizer_client
|
|
||||||
if _summarizer_client is None:
|
|
||||||
api_key = os.getenv("OPENROUTER_API_KEY")
|
|
||||||
if not api_key:
|
|
||||||
raise ValueError("OPENROUTER_API_KEY not set")
|
|
||||||
_summarizer_client = AsyncOpenAI(
|
|
||||||
api_key=api_key,
|
|
||||||
base_url=OPENROUTER_BASE_URL,
|
|
||||||
)
|
|
||||||
return _summarizer_client
|
|
||||||
|
|
||||||
|
|
||||||
def _format_conversation(messages: List[Dict[str, Any]]) -> str:
|
def _format_conversation(messages: List[Dict[str, Any]]) -> str:
|
||||||
"""Format session messages into a readable transcript for summarization."""
|
"""Format session messages into a readable transcript for summarization."""
|
||||||
|
|||||||
@@ -32,93 +32,19 @@ import logging
|
|||||||
import os
|
import os
|
||||||
import asyncio
|
import asyncio
|
||||||
import uuid
|
import uuid
|
||||||
import datetime
|
|
||||||
import base64
|
import base64
|
||||||
from pathlib import Path
|
from pathlib import Path
|
||||||
from typing import Dict, Any, Optional
|
from typing import Dict, Any, Optional
|
||||||
from openai import AsyncOpenAI
|
|
||||||
import httpx
|
import httpx
|
||||||
from hermes_constants import OPENROUTER_BASE_URL
|
from tools.openrouter_client import get_async_client as _get_openrouter_client, check_api_key as check_openrouter_api_key
|
||||||
|
from tools.debug_helpers import DebugSession
|
||||||
|
|
||||||
logger = logging.getLogger(__name__)
|
logger = logging.getLogger(__name__)
|
||||||
|
|
||||||
_openrouter_client = None
|
|
||||||
|
|
||||||
def _get_openrouter_client():
|
|
||||||
"""Get or create the OpenRouter client (lazy initialization)."""
|
|
||||||
global _openrouter_client
|
|
||||||
if _openrouter_client is None:
|
|
||||||
api_key = os.getenv("OPENROUTER_API_KEY")
|
|
||||||
if not api_key:
|
|
||||||
raise ValueError("OPENROUTER_API_KEY environment variable not set")
|
|
||||||
_openrouter_client = AsyncOpenAI(
|
|
||||||
api_key=api_key,
|
|
||||||
base_url=OPENROUTER_BASE_URL
|
|
||||||
)
|
|
||||||
return _openrouter_client
|
|
||||||
|
|
||||||
# Configuration for vision processing
|
# Configuration for vision processing
|
||||||
DEFAULT_VISION_MODEL = "google/gemini-3-flash-preview"
|
DEFAULT_VISION_MODEL = "google/gemini-3-flash-preview"
|
||||||
|
|
||||||
# Debug mode configuration
|
_debug = DebugSession("vision_tools", env_var="VISION_TOOLS_DEBUG")
|
||||||
DEBUG_MODE = os.getenv("VISION_TOOLS_DEBUG", "false").lower() == "true"
|
|
||||||
DEBUG_SESSION_ID = str(uuid.uuid4())
|
|
||||||
DEBUG_LOG_PATH = Path("./logs")
|
|
||||||
DEBUG_DATA = {
|
|
||||||
"session_id": DEBUG_SESSION_ID,
|
|
||||||
"start_time": datetime.datetime.now().isoformat(),
|
|
||||||
"debug_enabled": DEBUG_MODE,
|
|
||||||
"tool_calls": []
|
|
||||||
} if DEBUG_MODE else None
|
|
||||||
|
|
||||||
# Create logs directory if debug mode is enabled
|
|
||||||
if DEBUG_MODE:
|
|
||||||
DEBUG_LOG_PATH.mkdir(exist_ok=True)
|
|
||||||
logger.debug("Vision debug mode enabled - Session ID: %s", DEBUG_SESSION_ID)
|
|
||||||
|
|
||||||
|
|
||||||
def _log_debug_call(tool_name: str, call_data: Dict[str, Any]) -> None:
|
|
||||||
"""
|
|
||||||
Log a debug call entry to the global debug data structure.
|
|
||||||
|
|
||||||
Args:
|
|
||||||
tool_name (str): Name of the tool being called
|
|
||||||
call_data (Dict[str, Any]): Data about the call including parameters and results
|
|
||||||
"""
|
|
||||||
if not DEBUG_MODE or not DEBUG_DATA:
|
|
||||||
return
|
|
||||||
|
|
||||||
call_entry = {
|
|
||||||
"timestamp": datetime.datetime.now().isoformat(),
|
|
||||||
"tool_name": tool_name,
|
|
||||||
**call_data
|
|
||||||
}
|
|
||||||
|
|
||||||
DEBUG_DATA["tool_calls"].append(call_entry)
|
|
||||||
|
|
||||||
|
|
||||||
def _save_debug_log() -> None:
|
|
||||||
"""
|
|
||||||
Save the current debug data to a JSON file in the logs directory.
|
|
||||||
"""
|
|
||||||
if not DEBUG_MODE or not DEBUG_DATA:
|
|
||||||
return
|
|
||||||
|
|
||||||
try:
|
|
||||||
debug_filename = f"vision_tools_debug_{DEBUG_SESSION_ID}.json"
|
|
||||||
debug_filepath = DEBUG_LOG_PATH / debug_filename
|
|
||||||
|
|
||||||
# Update end time
|
|
||||||
DEBUG_DATA["end_time"] = datetime.datetime.now().isoformat()
|
|
||||||
DEBUG_DATA["total_calls"] = len(DEBUG_DATA["tool_calls"])
|
|
||||||
|
|
||||||
with open(debug_filepath, 'w', encoding='utf-8') as f:
|
|
||||||
json.dump(DEBUG_DATA, f, indent=2, ensure_ascii=False)
|
|
||||||
|
|
||||||
logger.debug("Vision debug log saved: %s", debug_filepath)
|
|
||||||
|
|
||||||
except Exception as e:
|
|
||||||
logger.error("Error saving vision debug log: %s", e)
|
|
||||||
|
|
||||||
|
|
||||||
def _validate_image_url(url: str) -> bool:
|
def _validate_image_url(url: str) -> bool:
|
||||||
@@ -395,8 +321,8 @@ async def vision_analyze_tool(
|
|||||||
debug_call_data["analysis_length"] = analysis_length
|
debug_call_data["analysis_length"] = analysis_length
|
||||||
|
|
||||||
# Log debug information
|
# Log debug information
|
||||||
_log_debug_call("vision_analyze_tool", debug_call_data)
|
_debug.log_call("vision_analyze_tool", debug_call_data)
|
||||||
_save_debug_log()
|
_debug.save()
|
||||||
|
|
||||||
return json.dumps(result, indent=2, ensure_ascii=False)
|
return json.dumps(result, indent=2, ensure_ascii=False)
|
||||||
|
|
||||||
@@ -411,8 +337,8 @@ async def vision_analyze_tool(
|
|||||||
}
|
}
|
||||||
|
|
||||||
debug_call_data["error"] = error_msg
|
debug_call_data["error"] = error_msg
|
||||||
_log_debug_call("vision_analyze_tool", debug_call_data)
|
_debug.log_call("vision_analyze_tool", debug_call_data)
|
||||||
_save_debug_log()
|
_debug.save()
|
||||||
|
|
||||||
return json.dumps(result, indent=2, ensure_ascii=False)
|
return json.dumps(result, indent=2, ensure_ascii=False)
|
||||||
|
|
||||||
@@ -426,16 +352,6 @@ async def vision_analyze_tool(
|
|||||||
logger.warning("Could not delete temporary file: %s", cleanup_error)
|
logger.warning("Could not delete temporary file: %s", cleanup_error)
|
||||||
|
|
||||||
|
|
||||||
def check_openrouter_api_key() -> bool:
|
|
||||||
"""
|
|
||||||
Check if the OpenRouter API key is available in environment variables.
|
|
||||||
|
|
||||||
Returns:
|
|
||||||
bool: True if API key is set, False otherwise
|
|
||||||
"""
|
|
||||||
return bool(os.getenv("OPENROUTER_API_KEY"))
|
|
||||||
|
|
||||||
|
|
||||||
def check_vision_requirements() -> bool:
|
def check_vision_requirements() -> bool:
|
||||||
"""
|
"""
|
||||||
Check if all requirements for vision tools are met.
|
Check if all requirements for vision tools are met.
|
||||||
@@ -453,20 +369,7 @@ def get_debug_session_info() -> Dict[str, Any]:
|
|||||||
Returns:
|
Returns:
|
||||||
Dict[str, Any]: Dictionary containing debug session information
|
Dict[str, Any]: Dictionary containing debug session information
|
||||||
"""
|
"""
|
||||||
if not DEBUG_MODE or not DEBUG_DATA:
|
return _debug.get_session_info()
|
||||||
return {
|
|
||||||
"enabled": False,
|
|
||||||
"session_id": None,
|
|
||||||
"log_path": None,
|
|
||||||
"total_calls": 0
|
|
||||||
}
|
|
||||||
|
|
||||||
return {
|
|
||||||
"enabled": True,
|
|
||||||
"session_id": DEBUG_SESSION_ID,
|
|
||||||
"log_path": str(DEBUG_LOG_PATH / f"vision_tools_debug_{DEBUG_SESSION_ID}.json"),
|
|
||||||
"total_calls": len(DEBUG_DATA["tool_calls"])
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
if __name__ == "__main__":
|
if __name__ == "__main__":
|
||||||
@@ -491,9 +394,9 @@ if __name__ == "__main__":
|
|||||||
print(f"🧠 Using model: {DEFAULT_VISION_MODEL}")
|
print(f"🧠 Using model: {DEFAULT_VISION_MODEL}")
|
||||||
|
|
||||||
# Show debug mode status
|
# Show debug mode status
|
||||||
if DEBUG_MODE:
|
if _debug.active:
|
||||||
print(f"🐛 Debug mode ENABLED - Session ID: {DEBUG_SESSION_ID}")
|
print(f"🐛 Debug mode ENABLED - Session ID: {_debug.session_id}")
|
||||||
print(f" Debug logs will be saved to: ./logs/vision_tools_debug_{DEBUG_SESSION_ID}.json")
|
print(f" Debug logs will be saved to: ./logs/vision_tools_debug_{_debug.session_id}.json")
|
||||||
else:
|
else:
|
||||||
print("🐛 Debug mode disabled (set VISION_TOOLS_DEBUG=true to enable)")
|
print("🐛 Debug mode disabled (set VISION_TOOLS_DEBUG=true to enable)")
|
||||||
|
|
||||||
|
|||||||
@@ -45,18 +45,13 @@ import logging
|
|||||||
import os
|
import os
|
||||||
import re
|
import re
|
||||||
import asyncio
|
import asyncio
|
||||||
import uuid
|
|
||||||
import datetime
|
|
||||||
from pathlib import Path
|
|
||||||
from typing import List, Dict, Any, Optional
|
from typing import List, Dict, Any, Optional
|
||||||
from firecrawl import Firecrawl
|
from firecrawl import Firecrawl
|
||||||
from openai import AsyncOpenAI
|
from tools.openrouter_client import get_async_client as _get_openrouter_client
|
||||||
from hermes_constants import OPENROUTER_BASE_URL
|
from tools.debug_helpers import DebugSession
|
||||||
|
|
||||||
logger = logging.getLogger(__name__)
|
logger = logging.getLogger(__name__)
|
||||||
|
|
||||||
# Initialize Firecrawl client lazily (only when needed)
|
|
||||||
# This prevents import errors when FIRECRAWL_API_KEY is not set
|
|
||||||
_firecrawl_client = None
|
_firecrawl_client = None
|
||||||
|
|
||||||
def _get_firecrawl_client():
|
def _get_firecrawl_client():
|
||||||
@@ -69,85 +64,10 @@ def _get_firecrawl_client():
|
|||||||
_firecrawl_client = Firecrawl(api_key=api_key)
|
_firecrawl_client = Firecrawl(api_key=api_key)
|
||||||
return _firecrawl_client
|
return _firecrawl_client
|
||||||
|
|
||||||
# Initialize OpenRouter API client lazily (only when needed)
|
|
||||||
_summarizer_client = None
|
|
||||||
|
|
||||||
def _get_summarizer_client():
|
|
||||||
"""Get or create the summarizer client (lazy initialization)."""
|
|
||||||
global _summarizer_client
|
|
||||||
if _summarizer_client is None:
|
|
||||||
api_key = os.getenv("OPENROUTER_API_KEY")
|
|
||||||
if not api_key:
|
|
||||||
raise ValueError("OPENROUTER_API_KEY environment variable not set")
|
|
||||||
_summarizer_client = AsyncOpenAI(
|
|
||||||
api_key=api_key,
|
|
||||||
base_url=OPENROUTER_BASE_URL
|
|
||||||
)
|
|
||||||
return _summarizer_client
|
|
||||||
|
|
||||||
# Configuration for LLM processing
|
|
||||||
DEFAULT_SUMMARIZER_MODEL = "google/gemini-3-flash-preview"
|
DEFAULT_SUMMARIZER_MODEL = "google/gemini-3-flash-preview"
|
||||||
DEFAULT_MIN_LENGTH_FOR_SUMMARIZATION = 5000
|
DEFAULT_MIN_LENGTH_FOR_SUMMARIZATION = 5000
|
||||||
|
|
||||||
# Debug mode configuration
|
_debug = DebugSession("web_tools", env_var="WEB_TOOLS_DEBUG")
|
||||||
DEBUG_MODE = os.getenv("WEB_TOOLS_DEBUG", "false").lower() == "true"
|
|
||||||
DEBUG_SESSION_ID = str(uuid.uuid4())
|
|
||||||
DEBUG_LOG_PATH = Path("./logs")
|
|
||||||
DEBUG_DATA = {
|
|
||||||
"session_id": DEBUG_SESSION_ID,
|
|
||||||
"start_time": datetime.datetime.now().isoformat(),
|
|
||||||
"debug_enabled": DEBUG_MODE,
|
|
||||||
"tool_calls": []
|
|
||||||
} if DEBUG_MODE else None
|
|
||||||
|
|
||||||
# Create logs directory if debug mode is enabled
|
|
||||||
if DEBUG_MODE:
|
|
||||||
DEBUG_LOG_PATH.mkdir(exist_ok=True)
|
|
||||||
logger.info("Debug mode enabled - Session ID: %s", DEBUG_SESSION_ID)
|
|
||||||
|
|
||||||
|
|
||||||
def _log_debug_call(tool_name: str, call_data: Dict[str, Any]) -> None:
|
|
||||||
"""
|
|
||||||
Log a debug call entry to the global debug data structure.
|
|
||||||
|
|
||||||
Args:
|
|
||||||
tool_name (str): Name of the tool being called
|
|
||||||
call_data (Dict[str, Any]): Data about the call including parameters and results
|
|
||||||
"""
|
|
||||||
if not DEBUG_MODE or not DEBUG_DATA:
|
|
||||||
return
|
|
||||||
|
|
||||||
call_entry = {
|
|
||||||
"timestamp": datetime.datetime.now().isoformat(),
|
|
||||||
"tool_name": tool_name,
|
|
||||||
**call_data
|
|
||||||
}
|
|
||||||
|
|
||||||
DEBUG_DATA["tool_calls"].append(call_entry)
|
|
||||||
|
|
||||||
|
|
||||||
def _save_debug_log() -> None:
|
|
||||||
"""
|
|
||||||
Save the current debug data to a JSON file in the logs directory.
|
|
||||||
"""
|
|
||||||
if not DEBUG_MODE or not DEBUG_DATA:
|
|
||||||
return
|
|
||||||
|
|
||||||
try:
|
|
||||||
debug_filename = f"web_tools_debug_{DEBUG_SESSION_ID}.json"
|
|
||||||
debug_filepath = DEBUG_LOG_PATH / debug_filename
|
|
||||||
|
|
||||||
# Update end time
|
|
||||||
DEBUG_DATA["end_time"] = datetime.datetime.now().isoformat()
|
|
||||||
DEBUG_DATA["total_calls"] = len(DEBUG_DATA["tool_calls"])
|
|
||||||
|
|
||||||
with open(debug_filepath, 'w', encoding='utf-8') as f:
|
|
||||||
json.dump(DEBUG_DATA, f, indent=2, ensure_ascii=False)
|
|
||||||
|
|
||||||
logger.debug("Debug log saved: %s", debug_filepath)
|
|
||||||
|
|
||||||
except Exception as e:
|
|
||||||
logger.error("Error saving debug log: %s", e)
|
|
||||||
|
|
||||||
|
|
||||||
async def process_content_with_llm(
|
async def process_content_with_llm(
|
||||||
@@ -303,7 +223,7 @@ Create a markdown summary that captures all key information in a well-organized,
|
|||||||
|
|
||||||
for attempt in range(max_retries):
|
for attempt in range(max_retries):
|
||||||
try:
|
try:
|
||||||
response = await _get_summarizer_client().chat.completions.create(
|
response = await _get_openrouter_client().chat.completions.create(
|
||||||
model=model,
|
model=model,
|
||||||
messages=[
|
messages=[
|
||||||
{"role": "system", "content": system_prompt},
|
{"role": "system", "content": system_prompt},
|
||||||
@@ -422,7 +342,7 @@ Synthesize these into ONE cohesive, comprehensive summary that:
|
|||||||
Create a single, unified markdown summary."""
|
Create a single, unified markdown summary."""
|
||||||
|
|
||||||
try:
|
try:
|
||||||
response = await _get_summarizer_client().chat.completions.create(
|
response = await _get_openrouter_client().chat.completions.create(
|
||||||
model=model,
|
model=model,
|
||||||
messages=[
|
messages=[
|
||||||
{"role": "system", "content": "You synthesize multiple summaries into one cohesive, comprehensive summary. Be thorough but concise."},
|
{"role": "system", "content": "You synthesize multiple summaries into one cohesive, comprehensive summary. Be thorough but concise."},
|
||||||
@@ -597,8 +517,8 @@ def web_search_tool(query: str, limit: int = 5) -> str:
|
|||||||
debug_call_data["final_response_size"] = len(result_json)
|
debug_call_data["final_response_size"] = len(result_json)
|
||||||
|
|
||||||
# Log debug information
|
# Log debug information
|
||||||
_log_debug_call("web_search_tool", debug_call_data)
|
_debug.log_call("web_search_tool", debug_call_data)
|
||||||
_save_debug_log()
|
_debug.save()
|
||||||
|
|
||||||
return result_json
|
return result_json
|
||||||
|
|
||||||
@@ -607,8 +527,8 @@ def web_search_tool(query: str, limit: int = 5) -> str:
|
|||||||
logger.error("%s", error_msg)
|
logger.error("%s", error_msg)
|
||||||
|
|
||||||
debug_call_data["error"] = error_msg
|
debug_call_data["error"] = error_msg
|
||||||
_log_debug_call("web_search_tool", debug_call_data)
|
_debug.log_call("web_search_tool", debug_call_data)
|
||||||
_save_debug_log()
|
_debug.save()
|
||||||
|
|
||||||
return json.dumps({"error": error_msg}, ensure_ascii=False)
|
return json.dumps({"error": error_msg}, ensure_ascii=False)
|
||||||
|
|
||||||
@@ -859,8 +779,8 @@ async def web_extract_tool(
|
|||||||
debug_call_data["processing_applied"].append("base64_image_removal")
|
debug_call_data["processing_applied"].append("base64_image_removal")
|
||||||
|
|
||||||
# Log debug information
|
# Log debug information
|
||||||
_log_debug_call("web_extract_tool", debug_call_data)
|
_debug.log_call("web_extract_tool", debug_call_data)
|
||||||
_save_debug_log()
|
_debug.save()
|
||||||
|
|
||||||
return cleaned_result
|
return cleaned_result
|
||||||
|
|
||||||
@@ -869,8 +789,8 @@ async def web_extract_tool(
|
|||||||
logger.error("%s", error_msg)
|
logger.error("%s", error_msg)
|
||||||
|
|
||||||
debug_call_data["error"] = error_msg
|
debug_call_data["error"] = error_msg
|
||||||
_log_debug_call("web_extract_tool", debug_call_data)
|
_debug.log_call("web_extract_tool", debug_call_data)
|
||||||
_save_debug_log()
|
_debug.save()
|
||||||
|
|
||||||
return json.dumps({"error": error_msg}, ensure_ascii=False)
|
return json.dumps({"error": error_msg}, ensure_ascii=False)
|
||||||
|
|
||||||
@@ -1149,8 +1069,8 @@ async def web_crawl_tool(
|
|||||||
debug_call_data["processing_applied"].append("base64_image_removal")
|
debug_call_data["processing_applied"].append("base64_image_removal")
|
||||||
|
|
||||||
# Log debug information
|
# Log debug information
|
||||||
_log_debug_call("web_crawl_tool", debug_call_data)
|
_debug.log_call("web_crawl_tool", debug_call_data)
|
||||||
_save_debug_log()
|
_debug.save()
|
||||||
|
|
||||||
return cleaned_result
|
return cleaned_result
|
||||||
|
|
||||||
@@ -1159,8 +1079,8 @@ async def web_crawl_tool(
|
|||||||
logger.error("%s", error_msg)
|
logger.error("%s", error_msg)
|
||||||
|
|
||||||
debug_call_data["error"] = error_msg
|
debug_call_data["error"] = error_msg
|
||||||
_log_debug_call("web_crawl_tool", debug_call_data)
|
_debug.log_call("web_crawl_tool", debug_call_data)
|
||||||
_save_debug_log()
|
_debug.save()
|
||||||
|
|
||||||
return json.dumps({"error": error_msg}, ensure_ascii=False)
|
return json.dumps({"error": error_msg}, ensure_ascii=False)
|
||||||
|
|
||||||
@@ -1187,30 +1107,8 @@ def check_nous_api_key() -> bool:
|
|||||||
|
|
||||||
|
|
||||||
def get_debug_session_info() -> Dict[str, Any]:
|
def get_debug_session_info() -> Dict[str, Any]:
|
||||||
"""
|
"""Get information about the current debug session."""
|
||||||
Get information about the current debug session.
|
return _debug.get_session_info()
|
||||||
|
|
||||||
Returns:
|
|
||||||
Dict[str, Any]: Dictionary containing debug session information:
|
|
||||||
- enabled: Whether debug mode is enabled
|
|
||||||
- session_id: Current session UUID (if enabled)
|
|
||||||
- log_path: Path where debug logs are saved (if enabled)
|
|
||||||
- total_calls: Number of tool calls logged so far (if enabled)
|
|
||||||
"""
|
|
||||||
if not DEBUG_MODE or not DEBUG_DATA:
|
|
||||||
return {
|
|
||||||
"enabled": False,
|
|
||||||
"session_id": None,
|
|
||||||
"log_path": None,
|
|
||||||
"total_calls": 0
|
|
||||||
}
|
|
||||||
|
|
||||||
return {
|
|
||||||
"enabled": True,
|
|
||||||
"session_id": DEBUG_SESSION_ID,
|
|
||||||
"log_path": str(DEBUG_LOG_PATH / f"web_tools_debug_{DEBUG_SESSION_ID}.json"),
|
|
||||||
"total_calls": len(DEBUG_DATA["tool_calls"])
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
if __name__ == "__main__":
|
if __name__ == "__main__":
|
||||||
@@ -1249,9 +1147,9 @@ if __name__ == "__main__":
|
|||||||
print(f" Default min length for processing: {DEFAULT_MIN_LENGTH_FOR_SUMMARIZATION} chars")
|
print(f" Default min length for processing: {DEFAULT_MIN_LENGTH_FOR_SUMMARIZATION} chars")
|
||||||
|
|
||||||
# Show debug mode status
|
# Show debug mode status
|
||||||
if DEBUG_MODE:
|
if _debug.active:
|
||||||
print(f"🐛 Debug mode ENABLED - Session ID: {DEBUG_SESSION_ID}")
|
print(f"🐛 Debug mode ENABLED - Session ID: {_debug.session_id}")
|
||||||
print(f" Debug logs will be saved to: ./logs/web_tools_debug_{DEBUG_SESSION_ID}.json")
|
print(f" Debug logs will be saved to: {_debug.log_dir}/web_tools_debug_{_debug.session_id}.json")
|
||||||
else:
|
else:
|
||||||
print("🐛 Debug mode disabled (set WEB_TOOLS_DEBUG=true to enable)")
|
print("🐛 Debug mode disabled (set WEB_TOOLS_DEBUG=true to enable)")
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user