diff --git a/litellm/proxy/management_endpoints/usage_endpoints/ai_usage_chat.py b/litellm/proxy/management_endpoints/usage_endpoints/ai_usage_chat.py index 4287ca3fc77..410883de6ac 100644 --- a/litellm/proxy/management_endpoints/usage_endpoints/ai_usage_chat.py +++ b/litellm/proxy/management_endpoints/usage_endpoints/ai_usage_chat.py @@ -449,14 +449,16 @@ async def _process_tool_call( """Execute a single tool call, yielding SSE events for status.""" fn_name = tc.function.name fn_args = json.loads(tc.function.arguments) + + allowed_names = {t["function"]["name"] for t in get_tools_for_role(is_admin)} handler = TOOL_HANDLERS.get(fn_name) - if not handler: + if fn_name not in allowed_names or not handler: chat_messages.append( { "role": "tool", "tool_call_id": tc.id, - "content": f"Unknown tool: {fn_name}", + "content": f"Tool not available: {fn_name}", } ) return @@ -475,8 +477,9 @@ async def _process_tool_call( ) yield _sse({**tool_event_base, "status": "complete"}) except Exception as e: - tool_result = f"Error: {e}" - yield _sse({**tool_event_base, "status": "error", "error": str(e)}) + verbose_proxy_logger.error("Tool %s failed: %s", fn_name, e) + tool_result = f"Error fetching {handler['label']}. Please try again." + yield _sse({**tool_event_base, "status": "error"}) chat_messages.append( {"role": "tool", "tool_call_id": tc.id, "content": tool_result} @@ -542,4 +545,9 @@ async def stream_usage_ai_chat( except Exception as e: verbose_proxy_logger.error("AI usage chat failed: %s", e) - yield _sse({"type": "error", "message": str(e)}) + yield _sse( + { + "type": "error", + "message": "An internal error occurred. Please try again.", + } + ) diff --git a/tests/test_litellm/proxy/management_endpoints/usage_endpoints/test_ai_usage_chat.py b/tests/test_litellm/proxy/management_endpoints/usage_endpoints/test_ai_usage_chat.py index f08f7ee58ec..9ca7898653c 100644 --- a/tests/test_litellm/proxy/management_endpoints/usage_endpoints/test_ai_usage_chat.py +++ b/tests/test_litellm/proxy/management_endpoints/usage_endpoints/test_ai_usage_chat.py @@ -313,7 +313,7 @@ class TestStreamUsageAiChat: error_events = [e for e in events if e["type"] == "error"] assert len(error_events) == 1 - assert "LLM error" in error_events[0]["message"] + assert "internal error" in error_events[0]["message"].lower() @pytest.mark.asyncio async def test_non_admin_enforces_user_id(self): diff --git a/ui/litellm-dashboard/tsconfig.json b/ui/litellm-dashboard/tsconfig.json index d24bdd340f7..5b0352feb98 100644 --- a/ui/litellm-dashboard/tsconfig.json +++ b/ui/litellm-dashboard/tsconfig.json @@ -14,7 +14,7 @@ "moduleResolution": "bundler", "resolveJsonModule": true, "isolatedModules": true, - "jsx": "react-jsx", + "jsx": "preserve", "incremental": true, "plugins": [ {