Add API usage tracking and dynamic task reloading
Features: - Usage tracking system (usage_tracker.py) - Tracks input/output tokens per API call - Calculates costs with support for cache pricing - Stores data in usage_data.json (gitignored) - Integrated into llm_interface.py - Dynamic task scheduler reloading - Auto-detects YAML changes every 60s - No restart needed for new tasks - reload_tasks() method for manual refresh - Example cost tracking scheduled task - Daily API usage report - Budget tracking ($5/month target) - Disabled by default in scheduled_tasks.yaml Improvements: - Fixed tool_use/tool_result pair splitting bug (CRITICAL) - Added thread safety to agent.chat() - Fixed N+1 query problem in hybrid search - Optimized database batch queries - Added conversation history pruning (50 messages max) Updated .gitignore: - Exclude user profiles (memory_workspace/users/*.md) - Exclude usage data (usage_data.json) - Exclude vector index (vectors.usearch) Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
This commit is contained in:
16
tools.py
16
tools.py
@@ -124,6 +124,10 @@ def execute_tool(tool_name: str, tool_input: Dict[str, Any]) -> str:
|
||||
return f"Error executing {tool_name}: {str(e)}"
|
||||
|
||||
|
||||
# Maximum characters of tool output to return (prevents token explosion)
|
||||
_MAX_TOOL_OUTPUT = 5000
|
||||
|
||||
|
||||
def _read_file(file_path: str) -> str:
|
||||
"""Read and return file contents."""
|
||||
path = Path(file_path)
|
||||
@@ -132,6 +136,8 @@ def _read_file(file_path: str) -> str:
|
||||
|
||||
try:
|
||||
content = path.read_text(encoding="utf-8")
|
||||
if len(content) > _MAX_TOOL_OUTPUT:
|
||||
content = content[:_MAX_TOOL_OUTPUT] + "\n... (file truncated)"
|
||||
return f"Content of {file_path}:\n\n{content}"
|
||||
except Exception as e:
|
||||
return f"Error reading file: {str(e)}"
|
||||
@@ -210,9 +216,15 @@ def _run_command(command: str, working_dir: str) -> str:
|
||||
|
||||
output = []
|
||||
if result.stdout:
|
||||
output.append(f"STDOUT:\n{result.stdout}")
|
||||
stdout = result.stdout
|
||||
if len(stdout) > _MAX_TOOL_OUTPUT:
|
||||
stdout = stdout[:_MAX_TOOL_OUTPUT] + "\n... (stdout truncated)"
|
||||
output.append(f"STDOUT:\n{stdout}")
|
||||
if result.stderr:
|
||||
output.append(f"STDERR:\n{result.stderr}")
|
||||
stderr = result.stderr
|
||||
if len(stderr) > _MAX_TOOL_OUTPUT:
|
||||
stderr = stderr[:_MAX_TOOL_OUTPUT] + "\n... (stderr truncated)"
|
||||
output.append(f"STDERR:\n{stderr}")
|
||||
|
||||
status = f"Command exited with code {result.returncode}"
|
||||
if not output:
|
||||
|
||||
Reference in New Issue
Block a user