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:
@@ -39,6 +39,7 @@ class SlackAdapter(BaseAdapter):
|
||||
super().__init__(config)
|
||||
self.app: Optional[AsyncApp] = None
|
||||
self.handler: Optional[AsyncSocketModeHandler] = None
|
||||
self._username_cache: Dict[str, str] = {} # user_id -> username
|
||||
|
||||
@property
|
||||
def platform_name(self) -> str:
|
||||
@@ -255,7 +256,15 @@ class SlackAdapter(BaseAdapter):
|
||||
}
|
||||
|
||||
async def _get_username(self, user_id: str) -> str:
|
||||
"""Get username from user ID."""
|
||||
"""Get username from user ID, with caching to avoid excessive API calls.
|
||||
|
||||
Sanitizes the returned username to contain only alphanumeric,
|
||||
hyphens, and underscores (matching memory_system validation rules).
|
||||
"""
|
||||
# Check cache first
|
||||
if user_id in self._username_cache:
|
||||
return self._username_cache[user_id]
|
||||
|
||||
if not self.app:
|
||||
return user_id
|
||||
|
||||
@@ -263,13 +272,20 @@ class SlackAdapter(BaseAdapter):
|
||||
result = await self.app.client.users_info(user=user_id)
|
||||
user = result["user"]
|
||||
profile = user.get("profile", {})
|
||||
return (
|
||||
raw_username = (
|
||||
profile.get("display_name")
|
||||
or profile.get("real_name")
|
||||
or user.get("name")
|
||||
or user_id
|
||||
)
|
||||
# Sanitize: replace spaces/special chars with underscores
|
||||
sanitized = "".join(
|
||||
c if c.isalnum() or c in "-_" else "_" for c in raw_username
|
||||
)
|
||||
self._username_cache[user_id] = sanitized
|
||||
return sanitized
|
||||
except SlackApiError:
|
||||
self._username_cache[user_id] = user_id
|
||||
return user_id
|
||||
|
||||
@staticmethod
|
||||
|
||||
Reference in New Issue
Block a user