From 30027d2928ce1a5aeef8f70b3116b961961aac80 Mon Sep 17 00:00:00 2001 From: yuneng-jiang Date: Tue, 3 Feb 2026 20:26:57 -0800 Subject: [PATCH 01/21] save empty endpoint as string --- litellm/proxy/db/db_spend_update_writer.py | 2 +- tests/test_litellm/proxy/db/test_db_spend_update_writer.py | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/litellm/proxy/db/db_spend_update_writer.py b/litellm/proxy/db/db_spend_update_writer.py index 429e56c805b..a6004813ba2 100644 --- a/litellm/proxy/db/db_spend_update_writer.py +++ b/litellm/proxy/db/db_spend_update_writer.py @@ -1227,7 +1227,7 @@ class DBSpendUpdateWriter: "custom_llm_provider": transaction.get( "custom_llm_provider" ), - "endpoint": transaction.get("endpoint"), + "endpoint": transaction.get("endpoint") or "", "prompt_tokens": transaction["prompt_tokens"], "completion_tokens": transaction["completion_tokens"], "spend": transaction["spend"], diff --git a/tests/test_litellm/proxy/db/test_db_spend_update_writer.py b/tests/test_litellm/proxy/db/test_db_spend_update_writer.py index 72403b0ba7b..4c5bb6a9479 100644 --- a/tests/test_litellm/proxy/db/test_db_spend_update_writer.py +++ b/tests/test_litellm/proxy/db/test_db_spend_update_writer.py @@ -132,7 +132,7 @@ async def test_update_daily_spend_with_null_entity_id(): assert create_data["model"] == "gpt-4" assert create_data["custom_llm_provider"] == "openai" assert create_data["mcp_namespaced_tool_name"] == "" - assert create_data["endpoint"] is None + assert create_data["endpoint"] == "" assert create_data["prompt_tokens"] == 10 assert create_data["completion_tokens"] == 20 assert create_data["spend"] == 0.1 @@ -194,7 +194,7 @@ async def test_update_daily_spend_sorting(): "model_group": None, "mcp_namespaced_tool_name": "", "custom_llm_provider": "openai", - "endpoint": None, + "endpoint": "", "prompt_tokens": 10, "completion_tokens": 20, "spend": 0.1, From 9ce55057ab2d9862440e8970a4de6d7cfb51fa44 Mon Sep 17 00:00:00 2001 From: yuneng-jiang Date: Tue, 3 Feb 2026 20:54:40 -0800 Subject: [PATCH 02/21] Adding logging for when batching fails --- litellm/proxy/db/db_spend_update_writer.py | 203 +++++++++--------- .../proxy/db/test_db_spend_update_writer.py | 124 ++++++++++- 2 files changed, 230 insertions(+), 97 deletions(-) diff --git a/litellm/proxy/db/db_spend_update_writer.py b/litellm/proxy/db/db_spend_update_writer.py index a6004813ba2..dc928921425 100644 --- a/litellm/proxy/db/db_spend_update_writer.py +++ b/litellm/proxy/db/db_spend_update_writer.py @@ -1187,119 +1187,130 @@ class DBSpendUpdateWriter: ) break - async with prisma_client.db.batch_() as batcher: - for _, transaction in transactions_to_process.items(): - entity_id = transaction.get(entity_id_field) + try: + async with prisma_client.db.batch_() as batcher: + for _, transaction in transactions_to_process.items(): + entity_id = transaction.get(entity_id_field) - # Construct the where clause dynamically - where_clause = { - unique_constraint_name: { + # Construct the where clause dynamically + where_clause = { + unique_constraint_name: { + entity_id_field: entity_id, + "date": transaction["date"], + "api_key": transaction["api_key"], + "model": transaction["model"], + "custom_llm_provider": transaction.get( + "custom_llm_provider" + ) + or "", + "mcp_namespaced_tool_name": transaction.get( + "mcp_namespaced_tool_name" + ) + or "", + "endpoint": transaction.get("endpoint") or "", + } + } + + # Get the table dynamically + table = getattr(batcher, table_name) + + # Common data structure for both create and update + common_data = { entity_id_field: entity_id, "date": transaction["date"], "api_key": transaction["api_key"], - "model": transaction["model"], - "custom_llm_provider": transaction.get( - "custom_llm_provider" - ) - or "", + "model": transaction.get("model"), + "model_group": transaction.get("model_group"), "mcp_namespaced_tool_name": transaction.get( "mcp_namespaced_tool_name" ) or "", + "custom_llm_provider": transaction.get( + "custom_llm_provider" + ), "endpoint": transaction.get("endpoint") or "", + "prompt_tokens": transaction["prompt_tokens"], + "completion_tokens": transaction["completion_tokens"], + "spend": transaction["spend"], + "api_requests": transaction["api_requests"], + "successful_requests": transaction[ + "successful_requests" + ], + "failed_requests": transaction["failed_requests"], } - } - # Get the table dynamically - table = getattr(batcher, table_name) - - # Common data structure for both create and update - common_data = { - entity_id_field: entity_id, - "date": transaction["date"], - "api_key": transaction["api_key"], - "model": transaction.get("model"), - "model_group": transaction.get("model_group"), - "mcp_namespaced_tool_name": transaction.get( - "mcp_namespaced_tool_name" - ) - or "", - "custom_llm_provider": transaction.get( - "custom_llm_provider" - ), - "endpoint": transaction.get("endpoint") or "", - "prompt_tokens": transaction["prompt_tokens"], - "completion_tokens": transaction["completion_tokens"], - "spend": transaction["spend"], - "api_requests": transaction["api_requests"], - "successful_requests": transaction[ - "successful_requests" - ], - "failed_requests": transaction["failed_requests"], - } - - # Add cache-related fields if they exist - if "cache_read_input_tokens" in transaction: - common_data["cache_read_input_tokens"] = ( - transaction.get("cache_read_input_tokens", 0) - ) - if "cache_creation_input_tokens" in transaction: - common_data["cache_creation_input_tokens"] = ( - transaction.get("cache_creation_input_tokens", 0) - ) - - if entity_type == "tag" and "request_id" in transaction: - common_data["request_id"] = transaction.get( - "request_id" - ) - - # Create update data structure - update_data = { - "prompt_tokens": { - "increment": transaction["prompt_tokens"] - }, - "completion_tokens": { - "increment": transaction["completion_tokens"] - }, - "spend": {"increment": transaction["spend"]}, - "api_requests": { - "increment": transaction["api_requests"] - }, - "successful_requests": { - "increment": transaction["successful_requests"] - }, - "failed_requests": { - "increment": transaction["failed_requests"] - }, - } - - # Add cache-related fields to update if they exist - if "cache_read_input_tokens" in transaction: - update_data["cache_read_input_tokens"] = { - "increment": transaction.get( - "cache_read_input_tokens", 0 + # Add cache-related fields if they exist + if "cache_read_input_tokens" in transaction: + common_data["cache_read_input_tokens"] = ( + transaction.get("cache_read_input_tokens", 0) ) - } - if "cache_creation_input_tokens" in transaction: - update_data["cache_creation_input_tokens"] = { - "increment": transaction.get( - "cache_creation_input_tokens", 0 + if "cache_creation_input_tokens" in transaction: + common_data["cache_creation_input_tokens"] = ( + transaction.get("cache_creation_input_tokens", 0) ) + + if entity_type == "tag" and "request_id" in transaction: + common_data["request_id"] = transaction.get( + "request_id" + ) + + # Create update data structure + update_data = { + "prompt_tokens": { + "increment": transaction["prompt_tokens"] + }, + "completion_tokens": { + "increment": transaction["completion_tokens"] + }, + "spend": {"increment": transaction["spend"]}, + "api_requests": { + "increment": transaction["api_requests"] + }, + "successful_requests": { + "increment": transaction["successful_requests"] + }, + "failed_requests": { + "increment": transaction["failed_requests"] + }, } - if entity_type == "tag" and "request_id" in transaction: - update_data["request_id"] = transaction.get("request_id") + # Add cache-related fields to update if they exist + if "cache_read_input_tokens" in transaction: + update_data["cache_read_input_tokens"] = { + "increment": transaction.get( + "cache_read_input_tokens", 0 + ) + } + if "cache_creation_input_tokens" in transaction: + update_data["cache_creation_input_tokens"] = { + "increment": transaction.get( + "cache_creation_input_tokens", 0 + ) + } - # Add endpoint to update_data so existing rows get their endpoint field updated - update_data["endpoint"] = transaction.get("endpoint") or "" + if entity_type == "tag" and "request_id" in transaction: + update_data["request_id"] = transaction.get("request_id") - table.upsert( - where=where_clause, - data={ - "create": common_data, - "update": update_data, - }, - ) + # Add endpoint to update_data so existing rows get their endpoint field updated + update_data["endpoint"] = transaction.get("endpoint") or "" + + table.upsert( + where=where_clause, + data={ + "create": common_data, + "update": update_data, + }, + ) + except Exception as batch_error: + # Log detailed error information for debugging batch upsert failures + # This helps diagnose issues like unique constraint violations + verbose_proxy_logger.exception( + f"Daily {entity_type} spend batch upsert failed. " + f"Table: {table_name}, Constraint: {unique_constraint_name}, " + f"Batch size: {len(transactions_to_process)}, " + f"Error: {str(batch_error)}" + ) + raise verbose_proxy_logger.debug( f"Processed {len(transactions_to_process)} daily {entity_type} transactions in {time.time() - start_time:.2f}s" diff --git a/tests/test_litellm/proxy/db/test_db_spend_update_writer.py b/tests/test_litellm/proxy/db/test_db_spend_update_writer.py index 4c5bb6a9479..6ccecf59eed 100644 --- a/tests/test_litellm/proxy/db/test_db_spend_update_writer.py +++ b/tests/test_litellm/proxy/db/test_db_spend_update_writer.py @@ -838,4 +838,126 @@ async def test_endpoint_field_is_correctly_mapped_from_call_type(): assert transaction["date"] == "2024-01-01" assert transaction["api_key"] == "test-key" assert transaction["model"] == "gpt-4" - assert transaction["custom_llm_provider"] == "openai" \ No newline at end of file + assert transaction["custom_llm_provider"] == "openai" + + +@pytest.mark.asyncio +async def test_update_daily_spend_logs_detailed_error_on_batch_upsert_failure(): + """ + Test that when batch upsert fails, detailed error information is logged. + This ensures proper debugging information is available for issues like unique constraint violations. + """ + from litellm._logging import verbose_proxy_logger + + # Setup + mock_prisma_client = MagicMock() + mock_batcher = MagicMock() + mock_table = MagicMock() + mock_batch_context = MagicMock() + mock_batch_context.__aenter__ = AsyncMock(return_value=mock_batcher) + mock_batcher.litellm_dailyuserspend = mock_table + + # Make the batch context manager's exit raise an exception + # This simulates a batch commit failure (e.g., unique constraint violation) + test_exception = Exception("Unique constraint violation") + mock_batch_context.__aexit__ = AsyncMock(side_effect=test_exception) + mock_prisma_client.db.batch_.return_value = mock_batch_context + + # Create a transaction + daily_spend_transactions = { + "test_key": { + "user_id": "test-user", + "date": "2024-01-01", + "api_key": "test-api-key", + "model": "gpt-4", + "custom_llm_provider": "openai", + "prompt_tokens": 10, + "completion_tokens": 20, + "spend": 0.1, + "api_requests": 1, + "successful_requests": 1, + "failed_requests": 0, + } + } + + # Create a mock proxy_logging_obj with failure_handler as AsyncMock + mock_proxy_logging = MagicMock() + mock_proxy_logging.failure_handler = AsyncMock() + + # Mock the logger to capture exception calls + with patch.object(verbose_proxy_logger, 'exception') as mock_exception_logger: + # Call the method and expect it to raise the exception + with pytest.raises(Exception, match="Unique constraint violation"): + await DBSpendUpdateWriter._update_daily_spend( + n_retry_times=0, # No retries to make test faster + prisma_client=mock_prisma_client, + proxy_logging_obj=mock_proxy_logging, + daily_spend_transactions=daily_spend_transactions, + entity_type="user", + entity_id_field="user_id", + table_name="litellm_dailyuserspend", + unique_constraint_name="user_id_date_api_key_model_custom_llm_provider_mcp_namespaced_tool_name_endpoint", + ) + + # Verify that exception was logged with detailed information + assert mock_exception_logger.called + call_args = mock_exception_logger.call_args[0][0] + assert "Daily user spend batch upsert failed" in call_args + assert "Table: litellm_dailyuserspend" in call_args + assert "Constraint: user_id_date_api_key_model_custom_llm_provider_mcp_namespaced_tool_name_endpoint" in call_args + assert "Batch size: 1" in call_args + assert "Unique constraint violation" in call_args + + +@pytest.mark.asyncio +async def test_update_daily_spend_re_raises_exception_after_logging(): + """ + Test that when batch upsert fails, the exception is properly re-raised after logging. + This ensures that error handling continues to work correctly upstream. + """ + # Setup + mock_prisma_client = MagicMock() + mock_batcher = MagicMock() + mock_table = MagicMock() + mock_batch_context = MagicMock() + mock_batch_context.__aenter__ = AsyncMock(return_value=mock_batcher) + mock_batcher.litellm_dailyuserspend = mock_table + + # Create a transaction + daily_spend_transactions = { + "test_key": { + "user_id": "test-user", + "date": "2024-01-01", + "api_key": "test-api-key", + "model": "gpt-4", + "custom_llm_provider": "openai", + "prompt_tokens": 10, + "completion_tokens": 20, + "spend": 0.1, + "api_requests": 1, + "successful_requests": 1, + "failed_requests": 0, + } + } + + # Create a custom exception to verify it's re-raised + custom_exception = ValueError("Database connection lost") + mock_batch_context.__aexit__ = AsyncMock(side_effect=custom_exception) + mock_prisma_client.db.batch_.return_value = mock_batch_context + + # Create a mock proxy_logging_obj with failure_handler as AsyncMock + mock_proxy_logging = MagicMock() + mock_proxy_logging.failure_handler = AsyncMock() + + # Verify the exception is re-raised + with pytest.raises(ValueError, match="Database connection lost"): + await DBSpendUpdateWriter._update_daily_spend( + n_retry_times=0, # No retries to make test faster + prisma_client=mock_prisma_client, + proxy_logging_obj=mock_proxy_logging, + daily_spend_transactions=daily_spend_transactions, + entity_type="user", + entity_id_field="user_id", + table_name="litellm_dailyuserspend", + unique_constraint_name="user_id_date_api_key_model_custom_llm_provider_mcp_namespaced_tool_name_endpoint", + ) \ No newline at end of file From 208cf5e86d8f86d0e2087fe21ac74d5051d5bf79 Mon Sep 17 00:00:00 2001 From: yuneng-jiang Date: Wed, 4 Feb 2026 11:53:03 -0800 Subject: [PATCH 03/21] refactor - rename search tools files --- ui/litellm-dashboard/src/app/page.tsx | 2 +- .../CreateSearchTools.tsx} | 12 ++++++------ .../SearchConnectionTest.tsx} | 0 .../SearchToolColumn.tsx} | 0 .../SearchToolTester.tsx} | 0 .../SearchToolView.tsx} | 12 +++++------- .../search_tools.tsx => SearchTools/SearchTools.tsx} | 6 +++--- .../src/components/SearchTools/index.tsx | 6 ++++++ .../{search_tools => SearchTools}/types.tsx | 0 .../src/components/search_tools/index.tsx | 6 ------ 10 files changed, 21 insertions(+), 23 deletions(-) rename ui/litellm-dashboard/src/components/{search_tools/create_search_tool.tsx => SearchTools/CreateSearchTools.tsx} (98%) rename ui/litellm-dashboard/src/components/{search_tools/search_connection_test.tsx => SearchTools/SearchConnectionTest.tsx} (100%) rename ui/litellm-dashboard/src/components/{search_tools/search_tool_columns.tsx => SearchTools/SearchToolColumn.tsx} (100%) rename ui/litellm-dashboard/src/components/{search_tools/search_tool_tester.tsx => SearchTools/SearchToolTester.tsx} (100%) rename ui/litellm-dashboard/src/components/{search_tools/search_tool_view.tsx => SearchTools/SearchToolView.tsx} (95%) rename ui/litellm-dashboard/src/components/{search_tools/search_tools.tsx => SearchTools/SearchTools.tsx} (98%) create mode 100644 ui/litellm-dashboard/src/components/SearchTools/index.tsx rename ui/litellm-dashboard/src/components/{search_tools => SearchTools}/types.tsx (100%) delete mode 100644 ui/litellm-dashboard/src/components/search_tools/index.tsx diff --git a/ui/litellm-dashboard/src/app/page.tsx b/ui/litellm-dashboard/src/app/page.tsx index 5f94db7e9f4..8e887d80fb3 100644 --- a/ui/litellm-dashboard/src/app/page.tsx +++ b/ui/litellm-dashboard/src/app/page.tsx @@ -27,7 +27,7 @@ import Organizations, { fetchOrganizations } from "@/components/organizations"; import PassThroughSettings from "@/components/pass_through_settings"; import PromptsPanel from "@/components/prompts"; import PublicModelHub from "@/components/public_model_hub"; -import { SearchTools } from "@/components/search_tools"; +import { SearchTools } from "@/components/SearchTools"; import Settings from "@/components/settings"; import { SurveyPrompt, SurveyModal, ClaudeCodePrompt, ClaudeCodeModal } from "@/components/survey"; import TagManagement from "@/components/tag_management"; diff --git a/ui/litellm-dashboard/src/components/search_tools/create_search_tool.tsx b/ui/litellm-dashboard/src/components/SearchTools/CreateSearchTools.tsx similarity index 98% rename from ui/litellm-dashboard/src/components/search_tools/create_search_tool.tsx rename to ui/litellm-dashboard/src/components/SearchTools/CreateSearchTools.tsx index 9dd14256eee..18eaf5e493e 100644 --- a/ui/litellm-dashboard/src/components/search_tools/create_search_tool.tsx +++ b/ui/litellm-dashboard/src/components/SearchTools/CreateSearchTools.tsx @@ -7,7 +7,7 @@ import { SearchTool, AvailableSearchProvider } from "./types"; import { isAdminRole } from "@/utils/roles"; import NotificationsManager from "../molecules/notifications_manager"; import { useQuery } from "@tanstack/react-query"; -import SearchConnectionTest from "./search_connection_test"; +import SearchConnectionTest from "./SearchConnectionTest"; import Image from "next/image"; const { TextArea } = Input; @@ -97,8 +97,8 @@ const CreateSearchTool: React.FC = ({ }, search_tool_info: formValues.description ? { - description: formValues.description, - } + description: formValues.description, + } : undefined, }; @@ -130,7 +130,7 @@ const CreateSearchTool: React.FC = ({ try { // Validate required fields for testing await form.validateFields(["search_provider", "api_key"]); - + setIsTestingConnection(true); // Generate a new test ID (using timestamp for uniqueness) setConnectionTestId(`test-${Date.now()}`); @@ -225,8 +225,8 @@ const CreateSearchTool: React.FC = ({ optionLabelProp="label" > {availableProviders.map((provider) => ( - = ({ size="small" icon={copiedStates["search-tool-name"] ? : } onClick={() => copyToClipboard(searchTool.search_tool_name, "search-tool-name")} - className={`left-2 z-10 transition-all duration-200 ${ - copiedStates["search-tool-name"] + className={`left-2 z-10 transition-all duration-200 ${copiedStates["search-tool-name"] ? "text-green-600 bg-green-50 border-green-200" : "text-gray-500 hover:text-gray-700 hover:bg-gray-100" - }`} + }`} />
@@ -67,11 +66,10 @@ export const SearchToolView: React.FC = ({ size="small" icon={copiedStates["search-tool-id"] ? : } onClick={() => copyToClipboard(searchTool.search_tool_id, "search-tool-id")} - className={`left-2 z-10 transition-all duration-200 ${ - copiedStates["search-tool-id"] + className={`left-2 z-10 transition-all duration-200 ${copiedStates["search-tool-id"] ? "text-green-600 bg-green-50 border-green-200" : "text-gray-500 hover:text-gray-700 hover:bg-gray-100" - }`} + }`} />
diff --git a/ui/litellm-dashboard/src/components/search_tools/search_tools.tsx b/ui/litellm-dashboard/src/components/SearchTools/SearchTools.tsx similarity index 98% rename from ui/litellm-dashboard/src/components/search_tools/search_tools.tsx rename to ui/litellm-dashboard/src/components/SearchTools/SearchTools.tsx index 2fbdd4d27c6..be4c74099b0 100644 --- a/ui/litellm-dashboard/src/components/search_tools/search_tools.tsx +++ b/ui/litellm-dashboard/src/components/SearchTools/SearchTools.tsx @@ -3,7 +3,7 @@ import { useQuery } from "@tanstack/react-query"; import { Modal, Form, Input, Select } from "antd"; import { Button, Title, Text, Grid, Col } from "@tremor/react"; import { DataTable } from "../view_logs/table"; -import { searchToolColumns } from "./search_tool_columns"; +import { searchToolColumns } from "./SearchToolColumn"; import { fetchSearchTools, updateSearchTool, @@ -13,8 +13,8 @@ import { import { SearchTool, AvailableSearchProvider } from "./types"; import { isAdminRole } from "@/utils/roles"; import NotificationsManager from "../molecules/notifications_manager"; -import { SearchToolView } from "./search_tool_view"; -import CreateSearchTool from "./create_search_tool"; +import { SearchToolView } from "./SearchToolView"; +import CreateSearchTool from "./CreateSearchTools"; interface SearchToolsProps { accessToken: string | null; diff --git a/ui/litellm-dashboard/src/components/SearchTools/index.tsx b/ui/litellm-dashboard/src/components/SearchTools/index.tsx new file mode 100644 index 00000000000..54820d38492 --- /dev/null +++ b/ui/litellm-dashboard/src/components/SearchTools/index.tsx @@ -0,0 +1,6 @@ +export { default as SearchTools } from './SearchTools'; +export { SearchToolView } from './SearchToolView'; +export { default as SearchConnectionTest } from './SearchConnectionTest'; +export { SearchToolTester } from './SearchToolTester'; +export * from './types'; + diff --git a/ui/litellm-dashboard/src/components/search_tools/types.tsx b/ui/litellm-dashboard/src/components/SearchTools/types.tsx similarity index 100% rename from ui/litellm-dashboard/src/components/search_tools/types.tsx rename to ui/litellm-dashboard/src/components/SearchTools/types.tsx diff --git a/ui/litellm-dashboard/src/components/search_tools/index.tsx b/ui/litellm-dashboard/src/components/search_tools/index.tsx deleted file mode 100644 index eae43a1d391..00000000000 --- a/ui/litellm-dashboard/src/components/search_tools/index.tsx +++ /dev/null @@ -1,6 +0,0 @@ -export { default as SearchTools } from './search_tools'; -export { SearchToolView } from './search_tool_view'; -export { default as SearchConnectionTest } from './search_connection_test'; -export { SearchToolTester } from './search_tool_tester'; -export * from './types'; - From 609c423314f290dd9c215ad5609ff21fd54ca79c Mon Sep 17 00:00:00 2001 From: yuneng-jiang Date: Wed, 4 Feb 2026 12:22:57 -0800 Subject: [PATCH 04/21] migrate to antd table --- .../SearchTools/SearchToolColumn.tsx | 170 +++++++++++------- .../components/SearchTools/SearchTools.tsx | 82 +++++---- .../src/components/SearchTools/types.tsx | 1 + 3 files changed, 151 insertions(+), 102 deletions(-) diff --git a/ui/litellm-dashboard/src/components/SearchTools/SearchToolColumn.tsx b/ui/litellm-dashboard/src/components/SearchTools/SearchToolColumn.tsx index 78aa1094000..86b0bde4d04 100644 --- a/ui/litellm-dashboard/src/components/SearchTools/SearchToolColumn.tsx +++ b/ui/litellm-dashboard/src/components/SearchTools/SearchToolColumn.tsx @@ -1,78 +1,114 @@ -import { ColumnDef } from "@tanstack/react-table"; +import { ColumnsType } from "antd/es/table"; import { SearchTool } from "./types"; -import { Icon } from "@tremor/react"; -import { PencilAltIcon, TrashIcon } from "@heroicons/react/outline"; +import { Tag } from "antd"; +import TableIconActionButton from "../common_components/IconActionButton/TableIconActionButtons/TableIconActionButton"; export const searchToolColumns = ( onView: (searchToolId: string) => void, onEdit: (searchToolId: string) => void, onDelete: (searchToolId: string) => void, availableProviders: Array<{ provider_name: string; ui_friendly_name: string }>, -): ColumnDef[] => [ - { - accessorKey: "search_tool_id", - header: "Search Tool ID", - cell: ({ row }) => ( - - ), - }, - { - accessorKey: "search_tool_name", - header: "Name", - cell: ({ getValue }) => {getValue() as string}, - }, - { - id: "provider", - header: "Provider", - cell: ({ row }) => { - const provider = row.original.litellm_params.search_provider; - const providerInfo = availableProviders.find((p) => p.provider_name === provider); - const displayName = providerInfo?.ui_friendly_name || provider; +): ColumnsType => [ + { + title: "Search Tool ID", + dataIndex: "search_tool_id", + key: "search_tool_id", + render: (_, tool) => { + const isFromConfig = tool.is_from_config; - return {displayName}; + if (isFromConfig) { + return -; + } + + return ( + + ); + }, }, - }, - { - header: "Created At", - accessorKey: "created_at", - sortingFn: "datetime", - cell: ({ row }) => { - const tool = row.original; - return {tool.created_at ? new Date(tool.created_at).toLocaleDateString() : "-"}; + { + title: "Name", + dataIndex: "search_tool_name", + key: "search_tool_name", + render: (name: string) => {name}, }, - }, - { - header: "Updated At", - accessorKey: "updated_at", - sortingFn: "datetime", - cell: ({ row }) => { - const tool = row.original; - return {tool.updated_at ? new Date(tool.updated_at).toLocaleDateString() : "-"}; + { + title: "Provider", + key: "provider", + render: (_, tool) => { + const provider = tool.litellm_params.search_provider; + const providerInfo = availableProviders.find((p) => p.provider_name === provider); + const displayName = providerInfo?.ui_friendly_name || provider; + + return {displayName}; + }, }, - }, - { - id: "actions", - header: "Actions", - cell: ({ row }) => ( -
- onEdit(row.original.search_tool_id!)} - className="cursor-pointer" - /> - onDelete(row.original.search_tool_id!)} - className="cursor-pointer" - /> -
- ), - }, -]; + { + title: "Created At", + dataIndex: "created_at", + key: "created_at", + render: (_, tool) => { + return {tool.created_at ? new Date(tool.created_at).toLocaleDateString() : "-"}; + }, + }, + { + title: "Updated At", + dataIndex: "updated_at", + key: "updated_at", + render: (_, tool) => { + return {tool.updated_at ? new Date(tool.updated_at).toLocaleDateString() : "-"}; + }, + }, + { + title: "Source", + key: "source", + render: (_, tool) => { + const isFromConfig = tool.is_from_config ?? false; + + return ( + + {isFromConfig ? "Config" : "DB"} + + ); + }, + }, + { + title: "Actions", + key: "actions", + render: (_, tool) => { + const toolId = tool.search_tool_id; + const isFromConfig = tool.is_from_config ?? false; + + return ( +
+ { + if (toolId && !isFromConfig) { + onEdit(toolId); + } + }} + /> + { + if (toolId && !isFromConfig) { + onDelete(toolId); + } + }} + /> +
+ ); + }, + }, + ]; diff --git a/ui/litellm-dashboard/src/components/SearchTools/SearchTools.tsx b/ui/litellm-dashboard/src/components/SearchTools/SearchTools.tsx index be4c74099b0..ba42ea22cdc 100644 --- a/ui/litellm-dashboard/src/components/SearchTools/SearchTools.tsx +++ b/ui/litellm-dashboard/src/components/SearchTools/SearchTools.tsx @@ -1,8 +1,8 @@ import React, { useState } from "react"; import { useQuery } from "@tanstack/react-query"; -import { Modal, Form, Input, Select } from "antd"; -import { Button, Title, Text, Grid, Col } from "@tremor/react"; -import { DataTable } from "../view_logs/table"; +import { Modal, Form, Input, Select, Table, Spin } from "antd"; +import { LoadingOutlined } from "@ant-design/icons"; +import { Button, Title, Text } from "@tremor/react"; import { searchToolColumns } from "./SearchToolColumn"; import { fetchSearchTools, @@ -15,6 +15,7 @@ import { isAdminRole } from "@/utils/roles"; import NotificationsManager from "../molecules/notifications_manager"; import { SearchToolView } from "./SearchToolView"; import CreateSearchTool from "./CreateSearchTools"; +import DeleteResourceModal from "../common_components/DeleteResourceModal"; interface SearchToolsProps { accessToken: string | null; @@ -22,24 +23,6 @@ interface SearchToolsProps { userID: string | null; } -const DeleteModal: React.FC<{ - isModalOpen: boolean; - title: string; - confirmDelete: () => void; - cancelDelete: () => void; -}> = ({ isModalOpen, title, confirmDelete, cancelDelete }) => { - if (!isModalOpen) return null; - return ( - - - {title} - -

Are you sure you want to delete this search tool?

- -
-
- ); -}; const SearchTools: React.FC = ({ accessToken, userRole, userID }) => { const { @@ -72,6 +55,7 @@ const SearchTools: React.FC = ({ accessToken, userRole, userID // State const [toolIdToDelete, setToolToDelete] = useState(null); const [isDeleteModalOpen, setIsDeleteModalOpen] = useState(false); + const [isDeleting, setIsDeleting] = useState(false); const [selectedToolId, setSelectedToolId] = useState(null); const [editTool, setEditTool] = useState(false); const [isCreateModalVisible, setCreateModalVisible] = useState(false); @@ -116,16 +100,19 @@ const SearchTools: React.FC = ({ accessToken, userRole, userID if (toolIdToDelete == null || accessToken == null) { return; } + setIsDeleting(true); try { await deleteSearchTool(accessToken, toolIdToDelete); NotificationsManager.success("Deleted search tool successfully"); + setIsDeleteModalOpen(false); + setToolToDelete(null); refetch(); } catch (error) { console.error("Error deleting the search tool:", error); NotificationsManager.error("Failed to delete search tool"); + } finally { + setIsDeleting(false); } - setIsDeleteModalOpen(false); - setToolToDelete(null); }; const cancelDelete = () => { @@ -133,6 +120,11 @@ const SearchTools: React.FC = ({ accessToken, userRole, userID setToolToDelete(null); }; + const toolToDelete = searchTools?.find((t) => t.search_tool_id === toolIdToDelete); + const providerInfo = toolToDelete + ? availableProviders.find((p) => p.provider_name === toolToDelete.litellm_params.search_provider) + : null; + const handleCreateSuccess = (newSearchTool: SearchTool) => { setCreateModalVisible(false); refetch(); @@ -231,26 +223,46 @@ const SearchTools: React.FC = ({ accessToken, userRole, userID /> ) : (
-
- } size="large"> +
} - getRowCanExpand={() => false} - isLoading={isLoadingTools} - noDataMessage="No search tools configured" + rowKey={(record) => record.search_tool_id || record.search_tool_name} + pagination={false} + locale={{ + emptyText: "No search tools configured", + }} + size="small" /> - + + ); return (
- Date: Wed, 4 Feb 2026 12:35:58 -0800 Subject: [PATCH 05/21] Adding tests --- .../SearchTools/CreateSearchTools.tsx | 16 +- .../SearchTools/SearchConnectionTest.tsx | 6 +- .../SearchTools/SearchToolColumn.tsx | 4 +- .../SearchTools/SearchToolView.test.tsx | 278 ++++++++++++++++++ .../components/SearchTools/SearchToolView.tsx | 18 +- .../SearchTools/SearchTools.test.tsx | 234 +++++++++++++++ .../components/SearchTools/SearchTools.tsx | 24 +- 7 files changed, 546 insertions(+), 34 deletions(-) create mode 100644 ui/litellm-dashboard/src/components/SearchTools/SearchToolView.test.tsx create mode 100644 ui/litellm-dashboard/src/components/SearchTools/SearchTools.test.tsx diff --git a/ui/litellm-dashboard/src/components/SearchTools/CreateSearchTools.tsx b/ui/litellm-dashboard/src/components/SearchTools/CreateSearchTools.tsx index 18eaf5e493e..49b57c2a884 100644 --- a/ui/litellm-dashboard/src/components/SearchTools/CreateSearchTools.tsx +++ b/ui/litellm-dashboard/src/components/SearchTools/CreateSearchTools.tsx @@ -1,14 +1,14 @@ -import React, { useState } from "react"; -import { Modal, Tooltip, Form, Select, Input, Typography } from "antd"; -import { InfoCircleOutlined } from "@ant-design/icons"; -import { Button, TextInput } from "@tremor/react"; -import { createSearchTool, fetchAvailableSearchProviders } from "../networking"; -import { SearchTool, AvailableSearchProvider } from "./types"; import { isAdminRole } from "@/utils/roles"; -import NotificationsManager from "../molecules/notifications_manager"; +import { InfoCircleOutlined } from "@ant-design/icons"; import { useQuery } from "@tanstack/react-query"; -import SearchConnectionTest from "./SearchConnectionTest"; +import { Button, TextInput } from "@tremor/react"; +import { Form, Input, Modal, Select, Tooltip, Typography } from "antd"; import Image from "next/image"; +import React, { useState } from "react"; +import NotificationsManager from "../molecules/notifications_manager"; +import { createSearchTool, fetchAvailableSearchProviders } from "../networking"; +import SearchConnectionTest from "./SearchConnectionTest"; +import { AvailableSearchProvider, SearchTool } from "./types"; const { TextArea } = Input; diff --git a/ui/litellm-dashboard/src/components/SearchTools/SearchConnectionTest.tsx b/ui/litellm-dashboard/src/components/SearchTools/SearchConnectionTest.tsx index e18d314591f..a8472cb1f8a 100644 --- a/ui/litellm-dashboard/src/components/SearchTools/SearchConnectionTest.tsx +++ b/ui/litellm-dashboard/src/components/SearchTools/SearchConnectionTest.tsx @@ -1,8 +1,8 @@ +import { InfoCircleOutlined, WarningOutlined } from "@ant-design/icons"; +import { Button, Divider, Typography } from "antd"; import React, { useEffect, useState } from "react"; -import { testSearchToolConnection } from "../networking"; -import { Button, Typography, Divider } from "antd"; -import { WarningOutlined, InfoCircleOutlined } from "@ant-design/icons"; import NotificationsManager from "../molecules/notifications_manager"; +import { testSearchToolConnection } from "../networking"; const { Text } = Typography; diff --git a/ui/litellm-dashboard/src/components/SearchTools/SearchToolColumn.tsx b/ui/litellm-dashboard/src/components/SearchTools/SearchToolColumn.tsx index 86b0bde4d04..e741bd06a99 100644 --- a/ui/litellm-dashboard/src/components/SearchTools/SearchToolColumn.tsx +++ b/ui/litellm-dashboard/src/components/SearchTools/SearchToolColumn.tsx @@ -1,7 +1,7 @@ -import { ColumnsType } from "antd/es/table"; -import { SearchTool } from "./types"; import { Tag } from "antd"; +import { ColumnsType } from "antd/es/table"; import TableIconActionButton from "../common_components/IconActionButton/TableIconActionButtons/TableIconActionButton"; +import { SearchTool } from "./types"; export const searchToolColumns = ( onView: (searchToolId: string) => void, diff --git a/ui/litellm-dashboard/src/components/SearchTools/SearchToolView.test.tsx b/ui/litellm-dashboard/src/components/SearchTools/SearchToolView.test.tsx new file mode 100644 index 00000000000..bb04a04a992 --- /dev/null +++ b/ui/litellm-dashboard/src/components/SearchTools/SearchToolView.test.tsx @@ -0,0 +1,278 @@ +import { render, screen, waitFor, within } from "@testing-library/react"; +import userEvent from "@testing-library/user-event"; +import { beforeEach, describe, expect, it, vi } from "vitest"; +import { SearchToolView } from "./SearchToolView"; +import { AvailableSearchProvider, SearchTool } from "./types"; + +vi.mock("@/utils/dataUtils", () => ({ + copyToClipboard: vi.fn().mockResolvedValue(true), +})); + +vi.mock("./SearchToolTester", () => ({ + SearchToolTester: ({ searchToolName, accessToken }: { searchToolName: string; accessToken: string }) => ( +
+ Search Tool Tester for {searchToolName} + Access Token: {accessToken} +
+ ), +})); + +describe("SearchToolView", () => { + const mockSearchTool: SearchTool = { + search_tool_id: "test-tool-id-123", + search_tool_name: "Test Search Tool", + litellm_params: { + search_provider: "perplexity", + api_key: "sk-test-key", + }, + search_tool_info: { + description: "Test description", + }, + created_at: "2024-01-15T10:30:00Z", + }; + + const mockAvailableProviders: AvailableSearchProvider[] = [ + { + provider_name: "perplexity", + ui_friendly_name: "Perplexity AI", + }, + { + provider_name: "tavily", + ui_friendly_name: "Tavily Search", + }, + ]; + + const defaultProps = { + searchTool: mockSearchTool, + onBack: vi.fn(), + isEditing: false, + accessToken: "test-token", + availableProviders: mockAvailableProviders, + }; + + beforeEach(async () => { + vi.clearAllMocks(); + const { copyToClipboard } = await import("@/utils/dataUtils"); + vi.mocked(copyToClipboard).mockResolvedValue(true); + }); + + it("should render", () => { + render(); + expect(screen.getByText("Test Search Tool")).toBeInTheDocument(); + }); + + it("should display search tool name", () => { + render(); + expect(screen.getByText("Test Search Tool")).toBeInTheDocument(); + }); + + it("should display search tool ID", () => { + render(); + expect(screen.getByText("test-tool-id-123")).toBeInTheDocument(); + }); + + it("should display provider name using UI-friendly name when available", () => { + render(); + expect(screen.getByText("Perplexity AI")).toBeInTheDocument(); + }); + + it("should display provider name using provider_name when UI-friendly name is not available", () => { + const searchToolWithoutProvider: SearchTool = { + ...mockSearchTool, + litellm_params: { + search_provider: "unknown-provider", + }, + }; + + render( + , + ); + expect(screen.getByText("unknown-provider")).toBeInTheDocument(); + }); + + it("should display masked API key when API key is set", () => { + render(); + expect(screen.getByText("****")).toBeInTheDocument(); + }); + + it("should display 'Not set' when API key is not set", () => { + const searchToolWithoutApiKey: SearchTool = { + ...mockSearchTool, + litellm_params: { + search_provider: "perplexity", + }, + }; + + render( + , + ); + expect(screen.getByText("Not set")).toBeInTheDocument(); + }); + + it("should display formatted created_at date", () => { + render(); + const dateText = screen.getByText(/2024-01-15/); + expect(dateText).toBeInTheDocument(); + }); + + it("should display 'Unknown' when created_at is not set", () => { + const searchToolWithoutDate: SearchTool = { + ...mockSearchTool, + created_at: undefined, + }; + + render( + , + ); + expect(screen.getByText("Unknown")).toBeInTheDocument(); + }); + + it("should display description when search_tool_info.description is provided", () => { + render(); + expect(screen.getByText("Test description")).toBeInTheDocument(); + }); + + it("should not display description card when search_tool_info.description is not provided", () => { + const searchToolWithoutDescription: SearchTool = { + ...mockSearchTool, + search_tool_info: {}, + }; + + render( + , + ); + expect(screen.queryByText("Description")).not.toBeInTheDocument(); + }); + + it("should call onBack when back button is clicked", async () => { + const user = userEvent.setup({ delay: null }); + const onBack = vi.fn(); + render(); + + const backButton = screen.getByRole("button", { name: /back to all search tools/i }); + await user.click(backButton); + + expect(onBack).toHaveBeenCalledTimes(1); + }); + + it("should copy search tool name to clipboard when copy button is clicked", async () => { + const user = userEvent.setup({ delay: null }); + const { copyToClipboard } = await import("@/utils/dataUtils"); + render(); + + const toolNameContainer = screen.getByText("Test Search Tool").closest("div"); + expect(toolNameContainer).toBeInTheDocument(); + + const copyButtons = within(toolNameContainer!).getAllByRole("button"); + const nameCopyButton = copyButtons.find((button) => { + return button.querySelector("svg") !== null; + }); + + expect(nameCopyButton).toBeInTheDocument(); + await user.click(nameCopyButton!); + + await waitFor(() => { + expect(copyToClipboard).toHaveBeenCalledWith("Test Search Tool"); + }); + }); + + it("should copy search tool ID to clipboard when copy button is clicked", async () => { + const user = userEvent.setup({ delay: null }); + const { copyToClipboard } = await import("@/utils/dataUtils"); + render(); + + const toolIdContainer = screen.getByText("test-tool-id-123").closest("div"); + expect(toolIdContainer).toBeInTheDocument(); + + const copyButtons = within(toolIdContainer!).getAllByRole("button"); + const idCopyButton = copyButtons.find((button) => { + return button.querySelector("svg") !== null; + }); + + expect(idCopyButton).toBeInTheDocument(); + await user.click(idCopyButton!); + + await waitFor(() => { + expect(copyToClipboard).toHaveBeenCalledWith("test-tool-id-123"); + }); + }); + + it("should show check icon after copying search tool name", async () => { + const user = userEvent.setup({ delay: null }); + const { copyToClipboard } = await import("@/utils/dataUtils"); + vi.mocked(copyToClipboard).mockResolvedValue(true); + + render(); + + const toolNameContainer = screen.getByText("Test Search Tool").closest("div"); + const copyButtons = within(toolNameContainer!).getAllByRole("button"); + const nameCopyButton = copyButtons.find((button) => { + return button.querySelector("svg") !== null; + }); + + expect(nameCopyButton).toBeInTheDocument(); + + const initialSvg = nameCopyButton!.querySelector("svg"); + expect(initialSvg).toBeInTheDocument(); + + await user.click(nameCopyButton!); + + await waitFor(() => { + const updatedSvg = nameCopyButton!.querySelector("svg"); + expect(updatedSvg).toBeInTheDocument(); + expect(nameCopyButton).toHaveClass("text-green-600"); + }); + }); + + + it("should not show check icon when copy fails", async () => { + const user = userEvent.setup({ delay: null }); + const { copyToClipboard } = await import("@/utils/dataUtils"); + vi.mocked(copyToClipboard).mockResolvedValue(false); + + render(); + + const toolNameContainer = screen.getByText("Test Search Tool").closest("div"); + const copyButtons = within(toolNameContainer!).getAllByRole("button"); + const nameCopyButton = copyButtons.find((button) => { + return button.querySelector("svg") !== null; + }); + + expect(nameCopyButton).toBeInTheDocument(); + await user.click(nameCopyButton!); + + await waitFor(() => { + expect(copyToClipboard).toHaveBeenCalledWith("Test Search Tool"); + }, { timeout: 3000 }); + + expect(nameCopyButton).not.toHaveClass("text-green-600"); + }); + + it("should render SearchToolTester when accessToken is provided", () => { + render(); + expect(screen.getByTestId("search-tool-tester")).toBeInTheDocument(); + expect(screen.getByText(/Search Tool Tester for Test Search Tool/)).toBeInTheDocument(); + }); + + it("should not render SearchToolTester when accessToken is null", () => { + render(); + expect(screen.queryByTestId("search-tool-tester")).not.toBeInTheDocument(); + }); + + it("should pass correct props to SearchToolTester", () => { + render(); + expect(screen.getByText("Access Token: test-token")).toBeInTheDocument(); + }); +}); diff --git a/ui/litellm-dashboard/src/components/SearchTools/SearchToolView.tsx b/ui/litellm-dashboard/src/components/SearchTools/SearchToolView.tsx index c07041471ed..ad88acd127f 100644 --- a/ui/litellm-dashboard/src/components/SearchTools/SearchToolView.tsx +++ b/ui/litellm-dashboard/src/components/SearchTools/SearchToolView.tsx @@ -1,11 +1,11 @@ -import React, { useState } from "react"; -import { ArrowLeftIcon } from "@heroicons/react/outline"; -import { Title, Card, Button, Text, Grid } from "@tremor/react"; -import { SearchTool, AvailableSearchProvider } from "./types"; import { copyToClipboard as utilCopyToClipboard } from "@/utils/dataUtils"; -import { CheckIcon, CopyIcon } from "lucide-react"; +import { ArrowLeftIcon } from "@heroicons/react/outline"; +import { Button, Card, Grid, Text, Title } from "@tremor/react"; import { Button as AntdButton } from "antd"; +import { CheckIcon, CopyIcon } from "lucide-react"; +import React, { useState } from "react"; import { SearchToolTester } from "./SearchToolTester"; +import { AvailableSearchProvider, SearchTool } from "./types"; interface SearchToolViewProps { searchTool: SearchTool; @@ -54,8 +54,8 @@ export const SearchToolView: React.FC = ({ icon={copiedStates["search-tool-name"] ? : } onClick={() => copyToClipboard(searchTool.search_tool_name, "search-tool-name")} className={`left-2 z-10 transition-all duration-200 ${copiedStates["search-tool-name"] - ? "text-green-600 bg-green-50 border-green-200" - : "text-gray-500 hover:text-gray-700 hover:bg-gray-100" + ? "text-green-600 bg-green-50 border-green-200" + : "text-gray-500 hover:text-gray-700 hover:bg-gray-100" }`} />
@@ -67,8 +67,8 @@ export const SearchToolView: React.FC = ({ icon={copiedStates["search-tool-id"] ? : } onClick={() => copyToClipboard(searchTool.search_tool_id, "search-tool-id")} className={`left-2 z-10 transition-all duration-200 ${copiedStates["search-tool-id"] - ? "text-green-600 bg-green-50 border-green-200" - : "text-gray-500 hover:text-gray-700 hover:bg-gray-100" + ? "text-green-600 bg-green-50 border-green-200" + : "text-gray-500 hover:text-gray-700 hover:bg-gray-100" }`} /> diff --git a/ui/litellm-dashboard/src/components/SearchTools/SearchTools.test.tsx b/ui/litellm-dashboard/src/components/SearchTools/SearchTools.test.tsx new file mode 100644 index 00000000000..f1f7bf8ab42 --- /dev/null +++ b/ui/litellm-dashboard/src/components/SearchTools/SearchTools.test.tsx @@ -0,0 +1,234 @@ +import * as roles from "@/utils/roles"; +import { QueryClient, QueryClientProvider } from "@tanstack/react-query"; +import { render, screen, waitFor } from "@testing-library/react"; +import userEvent from "@testing-library/user-event"; +import { beforeEach, describe, expect, it, vi } from "vitest"; +import * as networking from "../networking"; +import SearchTools from "./SearchTools"; +import { AvailableSearchProvider, SearchTool } from "./types"; + +vi.mock("../networking", () => ({ + fetchSearchTools: vi.fn(), + updateSearchTool: vi.fn(), + deleteSearchTool: vi.fn(), + fetchAvailableSearchProviders: vi.fn(), +})); + +vi.mock("@/utils/roles", () => ({ + isAdminRole: vi.fn(), +})); + +vi.mock("./SearchToolView", () => ({ + SearchToolView: ({ searchTool, onBack }: { searchTool: SearchTool; onBack: () => void }) => ( +
+
Search Tool View: {searchTool.search_tool_name}
+ +
+ ), +})); + +vi.mock("./CreateSearchTools", () => ({ + default: ({ + isModalVisible, + setModalVisible, + }: { + isModalVisible: boolean; + setModalVisible: (visible: boolean) => void; + }) => + isModalVisible ? ( +
+ +
+ ) : null, +})); + +vi.mock("../common_components/DeleteResourceModal", () => ({ + default: ({ + isOpen, + onOk, + onCancel, + }: { + isOpen: boolean; + onOk: () => void; + onCancel: () => void; + }) => + isOpen ? ( +
+ + +
+ ) : null, +})); + +const mockSearchTools: SearchTool[] = [ + { + search_tool_id: "tool-1", + search_tool_name: "Perplexity Search", + litellm_params: { + search_provider: "perplexity", + api_key: "sk-test-key", + }, + search_tool_info: { + description: "Test description", + }, + created_at: "2024-01-15T10:30:00Z", + }, + { + search_tool_id: "tool-2", + search_tool_name: "Tavily Search", + litellm_params: { + search_provider: "tavily", + }, + created_at: "2024-01-16T10:30:00Z", + }, +]; + +const mockAvailableProviders: AvailableSearchProvider[] = [ + { + provider_name: "perplexity", + ui_friendly_name: "Perplexity AI", + }, + { + provider_name: "tavily", + ui_friendly_name: "Tavily Search", + }, +]; + +const createWrapper = () => { + const queryClient = new QueryClient({ + defaultOptions: { + queries: { + retry: false, + }, + }, + }); + return ({ children }: { children: React.ReactNode }) => ( + {children} + ); +}; + +describe("SearchTools", () => { + const defaultProps = { + accessToken: "test-token", + userRole: "Admin", + userID: "user-1", + }; + + beforeEach(() => { + vi.clearAllMocks(); + vi.mocked(networking.fetchSearchTools).mockResolvedValue({ search_tools: mockSearchTools }); + vi.mocked(networking.fetchAvailableSearchProviders).mockResolvedValue({ providers: mockAvailableProviders }); + vi.mocked(roles.isAdminRole).mockReturnValue(true); + }); + + it("should render", async () => { + render(, { wrapper: createWrapper() }); + await waitFor(() => { + expect(screen.getByText("Search Tools")).toBeInTheDocument(); + }); + }); + + it("should display missing authentication parameters message when accessToken is missing", () => { + render(, { wrapper: createWrapper() }); + expect(screen.getByText("Missing required authentication parameters.")).toBeInTheDocument(); + }); + + it("should display missing authentication parameters message when userRole is missing", () => { + render(, { wrapper: createWrapper() }); + expect(screen.getByText("Missing required authentication parameters.")).toBeInTheDocument(); + }); + + it("should display missing authentication parameters message when userID is missing", () => { + render(, { wrapper: createWrapper() }); + expect(screen.getByText("Missing required authentication parameters.")).toBeInTheDocument(); + }); + + it("should display search tools table with tools", async () => { + render(, { wrapper: createWrapper() }); + await waitFor(() => { + expect(screen.getByText("Perplexity Search")).toBeInTheDocument(); + }); + expect(screen.getAllByText("Tavily Search").length).toBeGreaterThan(0); + }); + + it("should display empty state when no search tools are available", async () => { + vi.mocked(networking.fetchSearchTools).mockResolvedValue({ search_tools: [] }); + + render(, { wrapper: createWrapper() }); + await waitFor(() => { + expect(screen.getByText("No search tools configured")).toBeInTheDocument(); + }); + }); + + it("should show Add New Search Tool button when user is admin", async () => { + render(, { wrapper: createWrapper() }); + await waitFor(() => { + expect(screen.getByRole("button", { name: /add new search tool/i })).toBeInTheDocument(); + }); + }); + + it("should not show Add New Search Tool button when user is not admin", async () => { + vi.mocked(roles.isAdminRole).mockReturnValue(false); + + render(, { wrapper: createWrapper() }); + await waitFor(() => { + expect(screen.getByText("Search Tools")).toBeInTheDocument(); + }); + expect(screen.queryByRole("button", { name: /add new search tool/i })).not.toBeInTheDocument(); + }); + + it("should open create modal when Add New Search Tool button is clicked", async () => { + const user = userEvent.setup({ delay: null }); + render(, { wrapper: createWrapper() }); + + await waitFor(() => { + expect(screen.getByRole("button", { name: /add new search tool/i })).toBeInTheDocument(); + }); + + const addButton = screen.getByRole("button", { name: /add new search tool/i }); + await user.click(addButton); + + expect(screen.getByTestId("create-search-tool-modal")).toBeInTheDocument(); + }); + + it("should navigate to tool view when tool ID is clicked", async () => { + const user = userEvent.setup({ delay: null }); + render(, { wrapper: createWrapper() }); + + await waitFor(() => { + expect(screen.getByText("Perplexity Search")).toBeInTheDocument(); + }); + + const toolIdButton = screen.getByRole("button", { name: /tool-1/i }); + await user.click(toolIdButton); + + await waitFor(() => { + expect(screen.getByTestId("search-tool-view")).toBeInTheDocument(); + }); + expect(screen.getByText(/Search Tool View: Perplexity Search/i)).toBeInTheDocument(); + }); + + it("should navigate back from tool view to table", async () => { + const user = userEvent.setup({ delay: null }); + render(, { wrapper: createWrapper() }); + + await waitFor(() => { + expect(screen.getByText("Perplexity Search")).toBeInTheDocument(); + }); + + const toolIdButton = screen.getByRole("button", { name: /tool-1/i }); + await user.click(toolIdButton); + + await waitFor(() => { + expect(screen.getByTestId("search-tool-view")).toBeInTheDocument(); + }); + + const backButton = screen.getByRole("button", { name: /back/i }); + await user.click(backButton); + + await waitFor(() => { + expect(screen.queryByTestId("search-tool-view")).not.toBeInTheDocument(); + expect(screen.getByText("Perplexity Search")).toBeInTheDocument(); + }); + }); +}); diff --git a/ui/litellm-dashboard/src/components/SearchTools/SearchTools.tsx b/ui/litellm-dashboard/src/components/SearchTools/SearchTools.tsx index ba42ea22cdc..dd2033fc18f 100644 --- a/ui/litellm-dashboard/src/components/SearchTools/SearchTools.tsx +++ b/ui/litellm-dashboard/src/components/SearchTools/SearchTools.tsx @@ -1,21 +1,21 @@ -import React, { useState } from "react"; -import { useQuery } from "@tanstack/react-query"; -import { Modal, Form, Input, Select, Table, Spin } from "antd"; +import { isAdminRole } from "@/utils/roles"; import { LoadingOutlined } from "@ant-design/icons"; -import { Button, Title, Text } from "@tremor/react"; -import { searchToolColumns } from "./SearchToolColumn"; +import { useQuery } from "@tanstack/react-query"; +import { Button, Text, Title } from "@tremor/react"; +import { Form, Input, Modal, Select, Spin, Table } from "antd"; +import React, { useState } from "react"; +import DeleteResourceModal from "../common_components/DeleteResourceModal"; +import NotificationsManager from "../molecules/notifications_manager"; import { - fetchSearchTools, - updateSearchTool, deleteSearchTool, fetchAvailableSearchProviders, + fetchSearchTools, + updateSearchTool, } from "../networking"; -import { SearchTool, AvailableSearchProvider } from "./types"; -import { isAdminRole } from "@/utils/roles"; -import NotificationsManager from "../molecules/notifications_manager"; -import { SearchToolView } from "./SearchToolView"; import CreateSearchTool from "./CreateSearchTools"; -import DeleteResourceModal from "../common_components/DeleteResourceModal"; +import { searchToolColumns } from "./SearchToolColumn"; +import { SearchToolView } from "./SearchToolView"; +import { AvailableSearchProvider, SearchTool } from "./types"; interface SearchToolsProps { accessToken: string | null; From d1994a148dceb07721bc82d22e8936ecedb79a1c Mon Sep 17 00:00:00 2001 From: shin-bot-litellm Date: Wed, 4 Feb 2026 15:44:45 -0800 Subject: [PATCH 06/21] Fix mypy type error in fireworks_ai transformation (#20391) Cast message to dict before calling pop() to satisfy mypy's type checker. The message is typed as a Union of TypedDicts which don't have the 'provider_specific_fields' key, but the runtime check already confirms it's a dict with this key. --- litellm/llms/fireworks_ai/chat/transformation.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/litellm/llms/fireworks_ai/chat/transformation.py b/litellm/llms/fireworks_ai/chat/transformation.py index f6ea9c57f77..7ec32fecc46 100644 --- a/litellm/llms/fireworks_ai/chat/transformation.py +++ b/litellm/llms/fireworks_ai/chat/transformation.py @@ -239,7 +239,7 @@ class FireworksAIConfig(OpenAIGPTConfig): # Remove fields not permitted by FireworksAI that may cause: # "Not permitted, field: 'messages[n].provider_specific_fields'" if isinstance(message, dict) and "provider_specific_fields" in message: - message.pop("provider_specific_fields", None) + cast(dict, message).pop("provider_specific_fields", None) return messages From 555e1da9b49f66f236412fa95eaac0859adcb384 Mon Sep 17 00:00:00 2001 From: shivam Date: Wed, 4 Feb 2026 15:53:24 -0800 Subject: [PATCH 07/21] langfuse doc update --- .../observability/langfuse_integration.md | 60 +++++++++++++++++++ 1 file changed, 60 insertions(+) diff --git a/docs/my-website/docs/observability/langfuse_integration.md b/docs/my-website/docs/observability/langfuse_integration.md index a81336c5bc6..d3c5a44d481 100644 --- a/docs/my-website/docs/observability/langfuse_integration.md +++ b/docs/my-website/docs/observability/langfuse_integration.md @@ -215,6 +215,66 @@ The following parameters can be updated on a continuation of a trace by passing Any other key value pairs passed into the metadata not listed in the above spec for a `litellm` completion will be added as a metadata key value pair for the generation. +#### Multiple Langfuse Projects (Per-Request Credentials) + +You can send traces to different Langfuse projects per request by passing credentials directly to `completion()` or `acompletion()`. This works alongside (or instead of) the global env vars and is useful when different teams or business processes use different Langfuse projects. + +Pass **`langfuse_public_key`**, **`langfuse_secret_key`** (or **`langfuse_secret`**), and optionally **`langfuse_host`** as keyword arguments: + +```python +import litellm +from litellm import completion + +# Optional: set a default via env for requests that don't pass credentials +# os.environ["LANGFUSE_PUBLIC_KEY"] = "pk-default..." +# os.environ["LANGFUSE_SECRET_KEY"] = "sk-default..." + +litellm.success_callback = ["langfuse"] +litellm.failure_callback = ["langfuse"] + +# Request 1 → Langfuse Project A +response_a = completion( + model="gpt-3.5-turbo", + messages=[{"role": "user", "content": "Hello from team A"}], + langfuse_public_key="pk-lf-project-a...", + langfuse_secret_key="sk-lf-project-a...", + langfuse_host="https://us.cloud.langfuse.com", # optional +) + +# Request 2 → Langfuse Project B (different project) +response_b = completion( + model="gpt-3.5-turbo", + messages=[{"role": "user", "content": "Hello from team B"}], + langfuse_public_key="pk-lf-project-b...", + langfuse_secret_key="sk-lf-project-b...", + langfuse_host="https://eu.cloud.langfuse.com", # optional, can differ per project +) +``` + +Async usage with per-request credentials: + +```python +import litellm +from litellm import acompletion + +litellm.success_callback = ["langfuse"] +litellm.failure_callback = ["langfuse"] + +response = await acompletion( + model="gpt-3.5-turbo", + messages=[{"role": "user", "content": "Hi"}], + langfuse_public_key="pk-lf-...", + langfuse_secret_key="sk-lf-...", + langfuse_host="https://us.cloud.langfuse.com", # optional +) +``` + +- **`langfuse_public_key`** – Langfuse project public key (required for per-request override). +- **`langfuse_secret_key`** or **`langfuse_secret`** – Langfuse secret key (either name is accepted). +- **`langfuse_host`** – Langfuse host URL (e.g. `https://us.cloud.langfuse.com`); optional, defaults to env or Langfuse cloud. + +When these are passed, that request uses this project (and host) for the Langfuse callback; when omitted, the callback uses the global Langfuse client (from env vars if set). LiteLLM caches a Langfuse client per credential set to avoid creating a new client on every request. + #### Disable Logging - Specific Calls To disable logging for specific calls use the `no-log` flag. From 0209b214ace3dbe51d726b33e266a2e4af36634b Mon Sep 17 00:00:00 2001 From: shin-bot-litellm Date: Wed, 4 Feb 2026 16:07:17 -0800 Subject: [PATCH 08/21] fix(a2a): use text/event-stream SSE format for message/stream endpoint (#20365) * fix(a2a): use text/event-stream SSE format for message/stream endpoint The A2A gateway's streaming response was using application/x-ndjson Content-Type and raw NDJSON body format. The A2A protocol spec requires text/event-stream with SSE framing (data: ...\n\n). The official a2a-sdk client validates the Content-Type header and raises SSEError when it doesn't contain text/event-stream. Changes: - Changed media_type from application/x-ndjson to text/event-stream - Updated response body to use SSE framing (data: prefix + \n\n suffix) - Added tests validating Content-Type and SSE body format Fixes #20278 * Potential fix for code scanning alert no. 4045: Information exposure through an exception Co-authored-by: Copilot Autofix powered by AI <62310815+github-advanced-security[bot]@users.noreply.github.com> * test(a2a): add manual SSE format validation script Adds a manual test script that: 1. Starts a real A2A agent on port 10001 2. Starts LiteLLM proxy with the agent registered 3. Makes a streaming request to the proxy's A2A gateway 4. Validates Content-Type header is text/event-stream 5. Validates body uses SSE framing (data: ...\n\n) Run: python tests/a2a_manual/test_a2a_sse_manual.py --------- Co-authored-by: shin-bot-litellm Co-authored-by: Ishaan Jaff Co-authored-by: Copilot Autofix powered by AI <62310815+github-advanced-security[bot]@users.noreply.github.com> --- .../proxy/agent_endpoints/a2a_endpoints.py | 27 +- tests/a2a_manual/test_a2a_sse_manual.py | 261 ++++++++++++++++++ .../agent_endpoints/test_a2a_endpoints.py | 126 +++++++++ 3 files changed, 403 insertions(+), 11 deletions(-) create mode 100644 tests/a2a_manual/test_a2a_sse_manual.py diff --git a/litellm/proxy/agent_endpoints/a2a_endpoints.py b/litellm/proxy/agent_endpoints/a2a_endpoints.py index 24727aacd75..cc66e21b9d0 100644 --- a/litellm/proxy/agent_endpoints/a2a_endpoints.py +++ b/litellm/proxy/agent_endpoints/a2a_endpoints.py @@ -62,7 +62,7 @@ async def _handle_stream_message( if not A2A_SDK_AVAILABLE: # Return a streaming response that yields an error async def _error_stream(): - yield json.dumps( + yield "data: " + json.dumps( { "jsonrpc": "2.0", "id": request_id, @@ -71,9 +71,9 @@ async def _handle_stream_message( "message": "Server error: 'a2a' package not installed", }, } - ) + "\n" + ) + "\n\n" - return StreamingResponse(_error_stream(), media_type="application/x-ndjson") + return StreamingResponse(_error_stream(), media_type="text/event-stream") from a2a.types import ( MessageSendParams, @@ -96,22 +96,27 @@ async def _handle_stream_message( ): # Chunk may be dict or object depending on bridge vs standard path if hasattr(chunk, "model_dump"): - yield json.dumps( + yield "data: " + json.dumps( chunk.model_dump(mode="json", exclude_none=True) - ) + "\n" + ) + "\n\n" else: - yield json.dumps(chunk) + "\n" + yield "data: " + json.dumps(chunk) + "\n\n" except Exception as e: - verbose_proxy_logger.exception(f"Error streaming A2A response: {e}") - yield json.dumps( + # Log full exception details server-side for debugging + verbose_proxy_logger.exception("Error streaming A2A response") + # Return a generic error message to the client without exposing internal details + yield "data: " + json.dumps( { "jsonrpc": "2.0", "id": request_id, - "error": {"code": -32603, "message": f"Streaming error: {str(e)}"}, + "error": { + "code": -32603, + "message": "Streaming error", + }, } - ) + "\n" + ) + "\n\n" - return StreamingResponse(stream_response(), media_type="application/x-ndjson") + return StreamingResponse(stream_response(), media_type="text/event-stream") @router.get( diff --git a/tests/a2a_manual/test_a2a_sse_manual.py b/tests/a2a_manual/test_a2a_sse_manual.py new file mode 100644 index 00000000000..8205e5189ce --- /dev/null +++ b/tests/a2a_manual/test_a2a_sse_manual.py @@ -0,0 +1,261 @@ +#!/usr/bin/env python3 +""" +Manual test: Verify A2A streaming returns text/event-stream (SSE format) + +This script: +1. Starts a simple A2A agent on port 10001 +2. Starts LiteLLM proxy on port 4000 with the agent registered +3. Makes a streaming request to the proxy's A2A gateway +4. Validates Content-Type header and SSE body format + +Run: python test_a2a_sse_manual.py + +Expected output: + ✅ Content-Type: text/event-stream + ✅ SSE framing: data: {...}\n\n +""" + +import asyncio +import json +import os +import signal +import subprocess +import sys +import tempfile +import time + +import httpx + +AGENT_PORT = 10001 +PROXY_PORT = 4000 +TIMEOUT = 60 + + +def start_agent(): + """Start a simple A2A agent using LiteLLM's a2a_protocol.""" + agent_code = ''' +import asyncio +from litellm.a2a_protocol import A2AServer, BaseA2AAgent + +class TestAgent(BaseA2AAgent): + @property + def name(self) -> str: + return "test-agent" + + @property + def description(self) -> str: + return "Test agent for SSE validation" + + @property + def streaming(self) -> bool: + return True + + async def invoke(self, query, session_id=None): + return {"role": "agent", "parts": [{"kind": "text", "text": "Hello from test agent!"}]} + + async def invoke_streaming(self, query, session_id=None): + for word in ["Hello", "from", "streaming", "agent!"]: + yield {"role": "agent", "parts": [{"kind": "text", "text": word + " "}]} + await asyncio.sleep(0.1) + +async def main(): + server = A2AServer(agent=TestAgent(), host="0.0.0.0", port=10001) + await server.start() + +if __name__ == "__main__": + asyncio.run(main()) +''' + with tempfile.NamedTemporaryFile(mode='w', suffix='.py', delete=False) as f: + f.write(agent_code) + agent_file = f.name + + proc = subprocess.Popen( + [sys.executable, agent_file], + stdout=subprocess.PIPE, + stderr=subprocess.PIPE, + ) + return proc, agent_file + + +def start_proxy(): + """Start LiteLLM proxy with A2A agent registered.""" + config = { + "model_list": [ + { + "model_name": "gpt-4o-mini", + "litellm_params": { + "model": "gpt-4o-mini", + } + } + ], + "a2a_config": { + "agents": [ + { + "agent_id": "test-agent", + "api_base": f"http://localhost:{AGENT_PORT}", + } + ] + }, + "general_settings": { + "master_key": "sk-test-key" + } + } + + with tempfile.NamedTemporaryFile(mode='w', suffix='.yaml', delete=False) as f: + import yaml + yaml.dump(config, f) + config_file = f.name + + proc = subprocess.Popen( + [sys.executable, "-m", "litellm", "--config", config_file, "--port", str(PROXY_PORT)], + stdout=subprocess.PIPE, + stderr=subprocess.PIPE, + ) + return proc, config_file + + +async def wait_for_server(url: str, timeout: int = 30): + """Wait for a server to be ready.""" + start = time.time() + async with httpx.AsyncClient() as client: + while time.time() - start < timeout: + try: + resp = await client.get(url, timeout=2) + if resp.status_code < 500: + return True + except Exception: + pass + await asyncio.sleep(0.5) + return False + + +async def test_streaming(): + """Test the A2A streaming endpoint.""" + print("\n" + "=" * 60) + print("Testing A2A Streaming SSE Format") + print("=" * 60) + + url = f"http://localhost:{PROXY_PORT}/a2a/test-agent" + headers = { + "Content-Type": "application/json", + "Authorization": "Bearer sk-test-key", + } + payload = { + "jsonrpc": "2.0", + "id": "test-123", + "method": "message/stream", + "params": { + "message": { + "role": "user", + "parts": [{"kind": "text", "text": "Hello"}], + "messageId": "msg-001", + } + } + } + + print(f"\n📡 POST {url}") + print(f" Method: message/stream") + + async with httpx.AsyncClient() as client: + async with client.stream("POST", url, json=payload, headers=headers, timeout=30) as resp: + # Check Content-Type header + content_type = resp.headers.get("content-type", "") + print(f"\n📋 Response Headers:") + print(f" Content-Type: {content_type}") + + if "text/event-stream" in content_type: + print(" ✅ Correct! Uses text/event-stream (SSE)") + elif "application/x-ndjson" in content_type: + print(" ❌ WRONG! Still using application/x-ndjson") + return False + else: + print(f" ⚠️ Unexpected Content-Type") + + # Check body format + print(f"\n📦 Response Body (SSE events):") + events = [] + async for line in resp.aiter_lines(): + if line.strip(): + events.append(line) + print(f" {line[:100]}{'...' if len(line) > 100 else ''}") + + # Validate SSE framing + print(f"\n🔍 SSE Format Validation:") + all_valid = True + for i, event in enumerate(events): + if event.startswith("data: "): + try: + payload_str = event[6:] # Remove "data: " prefix + json.loads(payload_str) + print(f" Event {i+1}: ✅ Valid SSE (data: )") + except json.JSONDecodeError as e: + print(f" Event {i+1}: ❌ Invalid JSON: {e}") + all_valid = False + else: + print(f" Event {i+1}: ❌ Missing 'data: ' prefix") + all_valid = False + + if all_valid and events: + print(f"\n✅ ALL TESTS PASSED - A2A streaming uses correct SSE format") + return True + else: + print(f"\n❌ TESTS FAILED") + return False + + +async def main(): + agent_proc = None + proxy_proc = None + agent_file = None + config_file = None + + try: + print("🚀 Starting test A2A agent on port", AGENT_PORT) + agent_proc, agent_file = start_agent() + + print("⏳ Waiting for agent to be ready...") + if not await wait_for_server(f"http://localhost:{AGENT_PORT}/.well-known/agent.json"): + print("❌ Agent failed to start") + # Print agent stderr for debugging + if agent_proc.stderr: + print("Agent stderr:", agent_proc.stderr.read().decode()) + return 1 + print("✅ Agent ready") + + print("\n🚀 Starting LiteLLM proxy on port", PROXY_PORT) + proxy_proc, config_file = start_proxy() + + print("⏳ Waiting for proxy to be ready...") + if not await wait_for_server(f"http://localhost:{PROXY_PORT}/health"): + print("❌ Proxy failed to start") + if proxy_proc.stderr: + print("Proxy stderr:", proxy_proc.stderr.read().decode()) + return 1 + print("✅ Proxy ready") + + # Run the test + success = await test_streaming() + return 0 if success else 1 + + except Exception as e: + print(f"❌ Error: {e}") + import traceback + traceback.print_exc() + return 1 + + finally: + # Cleanup + if agent_proc: + agent_proc.terminate() + agent_proc.wait() + if proxy_proc: + proxy_proc.terminate() + proxy_proc.wait() + if agent_file and os.path.exists(agent_file): + os.unlink(agent_file) + if config_file and os.path.exists(config_file): + os.unlink(config_file) + + +if __name__ == "__main__": + sys.exit(asyncio.run(main())) diff --git a/tests/test_litellm/proxy/agent_endpoints/test_a2a_endpoints.py b/tests/test_litellm/proxy/agent_endpoints/test_a2a_endpoints.py index 9588c3b55c3..135e24953a9 100644 --- a/tests/test_litellm/proxy/agent_endpoints/test_a2a_endpoints.py +++ b/tests/test_litellm/proxy/agent_endpoints/test_a2a_endpoints.py @@ -4,6 +4,7 @@ Mock tests for A2A endpoints. Tests that invoke_agent_a2a properly integrates with add_litellm_data_to_request. """ +import json import sys from unittest.mock import AsyncMock, MagicMock, patch @@ -168,3 +169,128 @@ async def test_invoke_agent_a2a_adds_litellm_data(): # Verify proxy_server_request was added assert "proxy_server_request" in captured_data assert captured_data["proxy_server_request"]["method"] == "POST" + + +@pytest.mark.asyncio +async def test_handle_stream_message_returns_sse_content_type(): + """ + Test that _handle_stream_message returns Content-Type: text/event-stream + with SSE-framed body (data: ...\\n\\n), not application/x-ndjson. + + The A2A protocol spec requires text/event-stream for streaming responses. + The official a2a-sdk client validates this header. + + Ref: https://github.com/BerriAI/litellm/issues/20278 + """ + # Mock chunk with model_dump + mock_chunk = MagicMock() + mock_chunk.model_dump.return_value = { + "jsonrpc": "2.0", + "id": "test-id", + "result": {"kind": "status-update"}, + } + + async def mock_streaming(*args, **kwargs): + yield mock_chunk + + # Try to use real a2a.types if available + try: + from a2a.types import ( + MessageSendParams, + SendStreamingMessageRequest, + ) + except ImportError: + + class MessageSendParams: + def __init__(self, **kwargs): + self.__dict__.update(kwargs) + + class SendStreamingMessageRequest: + def __init__(self, **kwargs): + self.__dict__.update(kwargs) + + mock_a2a_types = MagicMock() + mock_a2a_types.MessageSendParams = MessageSendParams + mock_a2a_types.SendStreamingMessageRequest = SendStreamingMessageRequest + + with patch.dict( + sys.modules, + {"a2a": MagicMock(), "a2a.types": mock_a2a_types}, + ), patch( + "litellm.a2a_protocol.main.A2A_SDK_AVAILABLE", + True, + ), patch( + "litellm.a2a_protocol.asend_message_streaming", + side_effect=mock_streaming, + ): + from litellm.proxy.agent_endpoints.a2a_endpoints import ( + _handle_stream_message, + ) + + response = await _handle_stream_message( + api_base="http://backend:10001", + request_id="test-id", + params={ + "message": { + "role": "user", + "parts": [{"kind": "text", "text": "Hello"}], + "messageId": "msg-123", + } + }, + ) + + # Verify Content-Type is text/event-stream (required by A2A spec) + assert response.media_type == "text/event-stream" + + # Collect streamed body and verify SSE framing + body_parts = [] + async for chunk in response.body_iterator: + body_parts.append(chunk) + + assert len(body_parts) > 0 + for part in body_parts: + # Each SSE event must start with "data: " and end with "\n\n" + assert part.startswith("data: "), ( + f"SSE event must start with 'data: ', got: {part!r}" + ) + assert part.endswith("\n\n"), ( + f"SSE event must end with '\\n\\n', got: {part!r}" + ) + # The payload between "data: " and "\n\n" must be valid JSON + payload = part[len("data: "):-2] + parsed = json.loads(payload) + assert isinstance(parsed, dict) + + +@pytest.mark.asyncio +async def test_handle_stream_message_error_uses_sse_format(): + """ + Test that when A2A SDK is not available, the error stream also uses + text/event-stream with SSE framing. + """ + with patch( + "litellm.a2a_protocol.main.A2A_SDK_AVAILABLE", + False, + ): + from litellm.proxy.agent_endpoints.a2a_endpoints import ( + _handle_stream_message, + ) + + response = await _handle_stream_message( + api_base=None, + request_id="err-id", + params={}, + ) + + assert response.media_type == "text/event-stream" + + body_parts = [] + async for chunk in response.body_iterator: + body_parts.append(chunk) + + assert len(body_parts) == 1 + part = body_parts[0] + assert part.startswith("data: ") + assert part.endswith("\n\n") + payload = json.loads(part[len("data: "):-2]) + assert payload["error"]["code"] == -32603 From 6a73e5bd37fd44aad30f8e2ad3d597cae4d7260f Mon Sep 17 00:00:00 2001 From: Ishaan Jaff Date: Wed, 4 Feb 2026 16:08:22 -0800 Subject: [PATCH 09/21] =?UTF-8?q?Revert=20"fix(a2a):=20use=20text/event-st?= =?UTF-8?q?ream=20SSE=20format=20for=20message/stream=20endpoin=E2=80=A6"?= =?UTF-8?q?=20(#20446)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This reverts commit 0209b214ace3dbe51d726b33e266a2e4af36634b. --- .../proxy/agent_endpoints/a2a_endpoints.py | 27 +- tests/a2a_manual/test_a2a_sse_manual.py | 261 ------------------ .../agent_endpoints/test_a2a_endpoints.py | 126 --------- 3 files changed, 11 insertions(+), 403 deletions(-) delete mode 100644 tests/a2a_manual/test_a2a_sse_manual.py diff --git a/litellm/proxy/agent_endpoints/a2a_endpoints.py b/litellm/proxy/agent_endpoints/a2a_endpoints.py index cc66e21b9d0..24727aacd75 100644 --- a/litellm/proxy/agent_endpoints/a2a_endpoints.py +++ b/litellm/proxy/agent_endpoints/a2a_endpoints.py @@ -62,7 +62,7 @@ async def _handle_stream_message( if not A2A_SDK_AVAILABLE: # Return a streaming response that yields an error async def _error_stream(): - yield "data: " + json.dumps( + yield json.dumps( { "jsonrpc": "2.0", "id": request_id, @@ -71,9 +71,9 @@ async def _handle_stream_message( "message": "Server error: 'a2a' package not installed", }, } - ) + "\n\n" + ) + "\n" - return StreamingResponse(_error_stream(), media_type="text/event-stream") + return StreamingResponse(_error_stream(), media_type="application/x-ndjson") from a2a.types import ( MessageSendParams, @@ -96,27 +96,22 @@ async def _handle_stream_message( ): # Chunk may be dict or object depending on bridge vs standard path if hasattr(chunk, "model_dump"): - yield "data: " + json.dumps( + yield json.dumps( chunk.model_dump(mode="json", exclude_none=True) - ) + "\n\n" + ) + "\n" else: - yield "data: " + json.dumps(chunk) + "\n\n" + yield json.dumps(chunk) + "\n" except Exception as e: - # Log full exception details server-side for debugging - verbose_proxy_logger.exception("Error streaming A2A response") - # Return a generic error message to the client without exposing internal details - yield "data: " + json.dumps( + verbose_proxy_logger.exception(f"Error streaming A2A response: {e}") + yield json.dumps( { "jsonrpc": "2.0", "id": request_id, - "error": { - "code": -32603, - "message": "Streaming error", - }, + "error": {"code": -32603, "message": f"Streaming error: {str(e)}"}, } - ) + "\n\n" + ) + "\n" - return StreamingResponse(stream_response(), media_type="text/event-stream") + return StreamingResponse(stream_response(), media_type="application/x-ndjson") @router.get( diff --git a/tests/a2a_manual/test_a2a_sse_manual.py b/tests/a2a_manual/test_a2a_sse_manual.py deleted file mode 100644 index 8205e5189ce..00000000000 --- a/tests/a2a_manual/test_a2a_sse_manual.py +++ /dev/null @@ -1,261 +0,0 @@ -#!/usr/bin/env python3 -""" -Manual test: Verify A2A streaming returns text/event-stream (SSE format) - -This script: -1. Starts a simple A2A agent on port 10001 -2. Starts LiteLLM proxy on port 4000 with the agent registered -3. Makes a streaming request to the proxy's A2A gateway -4. Validates Content-Type header and SSE body format - -Run: python test_a2a_sse_manual.py - -Expected output: - ✅ Content-Type: text/event-stream - ✅ SSE framing: data: {...}\n\n -""" - -import asyncio -import json -import os -import signal -import subprocess -import sys -import tempfile -import time - -import httpx - -AGENT_PORT = 10001 -PROXY_PORT = 4000 -TIMEOUT = 60 - - -def start_agent(): - """Start a simple A2A agent using LiteLLM's a2a_protocol.""" - agent_code = ''' -import asyncio -from litellm.a2a_protocol import A2AServer, BaseA2AAgent - -class TestAgent(BaseA2AAgent): - @property - def name(self) -> str: - return "test-agent" - - @property - def description(self) -> str: - return "Test agent for SSE validation" - - @property - def streaming(self) -> bool: - return True - - async def invoke(self, query, session_id=None): - return {"role": "agent", "parts": [{"kind": "text", "text": "Hello from test agent!"}]} - - async def invoke_streaming(self, query, session_id=None): - for word in ["Hello", "from", "streaming", "agent!"]: - yield {"role": "agent", "parts": [{"kind": "text", "text": word + " "}]} - await asyncio.sleep(0.1) - -async def main(): - server = A2AServer(agent=TestAgent(), host="0.0.0.0", port=10001) - await server.start() - -if __name__ == "__main__": - asyncio.run(main()) -''' - with tempfile.NamedTemporaryFile(mode='w', suffix='.py', delete=False) as f: - f.write(agent_code) - agent_file = f.name - - proc = subprocess.Popen( - [sys.executable, agent_file], - stdout=subprocess.PIPE, - stderr=subprocess.PIPE, - ) - return proc, agent_file - - -def start_proxy(): - """Start LiteLLM proxy with A2A agent registered.""" - config = { - "model_list": [ - { - "model_name": "gpt-4o-mini", - "litellm_params": { - "model": "gpt-4o-mini", - } - } - ], - "a2a_config": { - "agents": [ - { - "agent_id": "test-agent", - "api_base": f"http://localhost:{AGENT_PORT}", - } - ] - }, - "general_settings": { - "master_key": "sk-test-key" - } - } - - with tempfile.NamedTemporaryFile(mode='w', suffix='.yaml', delete=False) as f: - import yaml - yaml.dump(config, f) - config_file = f.name - - proc = subprocess.Popen( - [sys.executable, "-m", "litellm", "--config", config_file, "--port", str(PROXY_PORT)], - stdout=subprocess.PIPE, - stderr=subprocess.PIPE, - ) - return proc, config_file - - -async def wait_for_server(url: str, timeout: int = 30): - """Wait for a server to be ready.""" - start = time.time() - async with httpx.AsyncClient() as client: - while time.time() - start < timeout: - try: - resp = await client.get(url, timeout=2) - if resp.status_code < 500: - return True - except Exception: - pass - await asyncio.sleep(0.5) - return False - - -async def test_streaming(): - """Test the A2A streaming endpoint.""" - print("\n" + "=" * 60) - print("Testing A2A Streaming SSE Format") - print("=" * 60) - - url = f"http://localhost:{PROXY_PORT}/a2a/test-agent" - headers = { - "Content-Type": "application/json", - "Authorization": "Bearer sk-test-key", - } - payload = { - "jsonrpc": "2.0", - "id": "test-123", - "method": "message/stream", - "params": { - "message": { - "role": "user", - "parts": [{"kind": "text", "text": "Hello"}], - "messageId": "msg-001", - } - } - } - - print(f"\n📡 POST {url}") - print(f" Method: message/stream") - - async with httpx.AsyncClient() as client: - async with client.stream("POST", url, json=payload, headers=headers, timeout=30) as resp: - # Check Content-Type header - content_type = resp.headers.get("content-type", "") - print(f"\n📋 Response Headers:") - print(f" Content-Type: {content_type}") - - if "text/event-stream" in content_type: - print(" ✅ Correct! Uses text/event-stream (SSE)") - elif "application/x-ndjson" in content_type: - print(" ❌ WRONG! Still using application/x-ndjson") - return False - else: - print(f" ⚠️ Unexpected Content-Type") - - # Check body format - print(f"\n📦 Response Body (SSE events):") - events = [] - async for line in resp.aiter_lines(): - if line.strip(): - events.append(line) - print(f" {line[:100]}{'...' if len(line) > 100 else ''}") - - # Validate SSE framing - print(f"\n🔍 SSE Format Validation:") - all_valid = True - for i, event in enumerate(events): - if event.startswith("data: "): - try: - payload_str = event[6:] # Remove "data: " prefix - json.loads(payload_str) - print(f" Event {i+1}: ✅ Valid SSE (data: )") - except json.JSONDecodeError as e: - print(f" Event {i+1}: ❌ Invalid JSON: {e}") - all_valid = False - else: - print(f" Event {i+1}: ❌ Missing 'data: ' prefix") - all_valid = False - - if all_valid and events: - print(f"\n✅ ALL TESTS PASSED - A2A streaming uses correct SSE format") - return True - else: - print(f"\n❌ TESTS FAILED") - return False - - -async def main(): - agent_proc = None - proxy_proc = None - agent_file = None - config_file = None - - try: - print("🚀 Starting test A2A agent on port", AGENT_PORT) - agent_proc, agent_file = start_agent() - - print("⏳ Waiting for agent to be ready...") - if not await wait_for_server(f"http://localhost:{AGENT_PORT}/.well-known/agent.json"): - print("❌ Agent failed to start") - # Print agent stderr for debugging - if agent_proc.stderr: - print("Agent stderr:", agent_proc.stderr.read().decode()) - return 1 - print("✅ Agent ready") - - print("\n🚀 Starting LiteLLM proxy on port", PROXY_PORT) - proxy_proc, config_file = start_proxy() - - print("⏳ Waiting for proxy to be ready...") - if not await wait_for_server(f"http://localhost:{PROXY_PORT}/health"): - print("❌ Proxy failed to start") - if proxy_proc.stderr: - print("Proxy stderr:", proxy_proc.stderr.read().decode()) - return 1 - print("✅ Proxy ready") - - # Run the test - success = await test_streaming() - return 0 if success else 1 - - except Exception as e: - print(f"❌ Error: {e}") - import traceback - traceback.print_exc() - return 1 - - finally: - # Cleanup - if agent_proc: - agent_proc.terminate() - agent_proc.wait() - if proxy_proc: - proxy_proc.terminate() - proxy_proc.wait() - if agent_file and os.path.exists(agent_file): - os.unlink(agent_file) - if config_file and os.path.exists(config_file): - os.unlink(config_file) - - -if __name__ == "__main__": - sys.exit(asyncio.run(main())) diff --git a/tests/test_litellm/proxy/agent_endpoints/test_a2a_endpoints.py b/tests/test_litellm/proxy/agent_endpoints/test_a2a_endpoints.py index 135e24953a9..9588c3b55c3 100644 --- a/tests/test_litellm/proxy/agent_endpoints/test_a2a_endpoints.py +++ b/tests/test_litellm/proxy/agent_endpoints/test_a2a_endpoints.py @@ -4,7 +4,6 @@ Mock tests for A2A endpoints. Tests that invoke_agent_a2a properly integrates with add_litellm_data_to_request. """ -import json import sys from unittest.mock import AsyncMock, MagicMock, patch @@ -169,128 +168,3 @@ async def test_invoke_agent_a2a_adds_litellm_data(): # Verify proxy_server_request was added assert "proxy_server_request" in captured_data assert captured_data["proxy_server_request"]["method"] == "POST" - - -@pytest.mark.asyncio -async def test_handle_stream_message_returns_sse_content_type(): - """ - Test that _handle_stream_message returns Content-Type: text/event-stream - with SSE-framed body (data: ...\\n\\n), not application/x-ndjson. - - The A2A protocol spec requires text/event-stream for streaming responses. - The official a2a-sdk client validates this header. - - Ref: https://github.com/BerriAI/litellm/issues/20278 - """ - # Mock chunk with model_dump - mock_chunk = MagicMock() - mock_chunk.model_dump.return_value = { - "jsonrpc": "2.0", - "id": "test-id", - "result": {"kind": "status-update"}, - } - - async def mock_streaming(*args, **kwargs): - yield mock_chunk - - # Try to use real a2a.types if available - try: - from a2a.types import ( - MessageSendParams, - SendStreamingMessageRequest, - ) - except ImportError: - - class MessageSendParams: - def __init__(self, **kwargs): - self.__dict__.update(kwargs) - - class SendStreamingMessageRequest: - def __init__(self, **kwargs): - self.__dict__.update(kwargs) - - mock_a2a_types = MagicMock() - mock_a2a_types.MessageSendParams = MessageSendParams - mock_a2a_types.SendStreamingMessageRequest = SendStreamingMessageRequest - - with patch.dict( - sys.modules, - {"a2a": MagicMock(), "a2a.types": mock_a2a_types}, - ), patch( - "litellm.a2a_protocol.main.A2A_SDK_AVAILABLE", - True, - ), patch( - "litellm.a2a_protocol.asend_message_streaming", - side_effect=mock_streaming, - ): - from litellm.proxy.agent_endpoints.a2a_endpoints import ( - _handle_stream_message, - ) - - response = await _handle_stream_message( - api_base="http://backend:10001", - request_id="test-id", - params={ - "message": { - "role": "user", - "parts": [{"kind": "text", "text": "Hello"}], - "messageId": "msg-123", - } - }, - ) - - # Verify Content-Type is text/event-stream (required by A2A spec) - assert response.media_type == "text/event-stream" - - # Collect streamed body and verify SSE framing - body_parts = [] - async for chunk in response.body_iterator: - body_parts.append(chunk) - - assert len(body_parts) > 0 - for part in body_parts: - # Each SSE event must start with "data: " and end with "\n\n" - assert part.startswith("data: "), ( - f"SSE event must start with 'data: ', got: {part!r}" - ) - assert part.endswith("\n\n"), ( - f"SSE event must end with '\\n\\n', got: {part!r}" - ) - # The payload between "data: " and "\n\n" must be valid JSON - payload = part[len("data: "):-2] - parsed = json.loads(payload) - assert isinstance(parsed, dict) - - -@pytest.mark.asyncio -async def test_handle_stream_message_error_uses_sse_format(): - """ - Test that when A2A SDK is not available, the error stream also uses - text/event-stream with SSE framing. - """ - with patch( - "litellm.a2a_protocol.main.A2A_SDK_AVAILABLE", - False, - ): - from litellm.proxy.agent_endpoints.a2a_endpoints import ( - _handle_stream_message, - ) - - response = await _handle_stream_message( - api_base=None, - request_id="err-id", - params={}, - ) - - assert response.media_type == "text/event-stream" - - body_parts = [] - async for chunk in response.body_iterator: - body_parts.append(chunk) - - assert len(body_parts) == 1 - part = body_parts[0] - assert part.startswith("data: ") - assert part.endswith("\n\n") - payload = json.loads(part[len("data: "):-2]) - assert payload["error"]["code"] == -32603 From 2a3843aa572d773bc1bfe733e25bbe31e3ead8aa Mon Sep 17 00:00:00 2001 From: Ishaan Jaff Date: Wed, 4 Feb 2026 16:37:40 -0800 Subject: [PATCH 10/21] [Fix] inconsistent response format in anthropic.messages.acreate() when using non anthropic providers (#20442) * _translate_openai_content_to_anthropic * test_response_format_consistency * test fixes unit tests * test fix * fix: use dict access for anthropic content blocks in tests (#20447) The translate_openai_response_to_anthropic method returns dicts, not objects. Changed .type/.text/.thinking attribute access to dict ['key'] access. --------- Co-authored-by: shin-bot-litellm --- .../adapters/transformation.py | 28 ++------ .../base_anthropic_unified_messages_test.py | 61 +++++++++++++++++ .../test_anthropic_messages_passthrough.py | 2 +- ...al_pass_through_adapters_transformation.py | 66 +++++++++---------- 4 files changed, 102 insertions(+), 55 deletions(-) diff --git a/litellm/llms/anthropic/experimental_pass_through/adapters/transformation.py b/litellm/llms/anthropic/experimental_pass_through/adapters/transformation.py index 444f821c20a..169b138a5f7 100644 --- a/litellm/llms/anthropic/experimental_pass_through/adapters/transformation.py +++ b/litellm/llms/anthropic/experimental_pass_through/adapters/transformation.py @@ -939,22 +939,8 @@ class LiteLLMAnthropicMessagesAdapter: self, choices: List[Choices], tool_name_mapping: Optional[Dict[str, str]] = None, - ) -> List[ - Union[ - AnthropicResponseContentBlockText, - AnthropicResponseContentBlockToolUse, - AnthropicResponseContentBlockThinking, - AnthropicResponseContentBlockRedactedThinking, - ] - ]: - new_content: List[ - Union[ - AnthropicResponseContentBlockText, - AnthropicResponseContentBlockToolUse, - AnthropicResponseContentBlockThinking, - AnthropicResponseContentBlockRedactedThinking, - ] - ] = [] + ) -> List[Dict[str, Any]]: + new_content: List[Dict[str, Any]] = [] for choice in choices: # Handle thinking blocks first if ( @@ -978,7 +964,7 @@ class LiteLLMAnthropicMessagesAdapter: if signature_value is not None else None ), - ) + ).model_dump() ) elif thinking_block.get("type") == "redacted_thinking": data_value = thinking_block.get("data", "") @@ -986,7 +972,7 @@ class LiteLLMAnthropicMessagesAdapter: AnthropicResponseContentBlockRedactedThinking( type="redacted_thinking", data=str(data_value) if data_value is not None else "", - ) + ).model_dump() ) # Handle reasoning_content when thinking_blocks is not present elif ( @@ -998,7 +984,7 @@ class LiteLLMAnthropicMessagesAdapter: type="thinking", thinking=str(choice.message.reasoning_content), signature=None, - ) + ).model_dump() ) # Handle text content @@ -1006,7 +992,7 @@ class LiteLLMAnthropicMessagesAdapter: new_content.append( AnthropicResponseContentBlockText( type="text", text=choice.message.content - ) + ).model_dump() ) # Handle tool calls (in parallel to text content) if ( @@ -1044,7 +1030,7 @@ class LiteLLMAnthropicMessagesAdapter: tool_use_block.provider_specific_fields = ( provider_specific_fields ) - new_content.append(tool_use_block) + new_content.append(tool_use_block.model_dump()) return new_content diff --git a/tests/pass_through_unit_tests/base_anthropic_unified_messages_test.py b/tests/pass_through_unit_tests/base_anthropic_unified_messages_test.py index b334966b441..2ebf9174e29 100644 --- a/tests/pass_through_unit_tests/base_anthropic_unified_messages_test.py +++ b/tests/pass_through_unit_tests/base_anthropic_unified_messages_test.py @@ -130,6 +130,67 @@ class BaseAnthropicMessagesTest: return collected_chunks + @pytest.mark.asyncio + async def test_response_format_consistency(self): + """ + Test that response content blocks are consistently dicts (not Pydantic objects). + + This ensures that code like response["content"][0]["type"] works + regardless of the target provider. + + Issue: https://github.com/BerriAI/litellm/issues/20342 + """ + litellm._turn_on_debug() + + request_params = self.model_config + + # Set up test parameters + messages = [{"role": "user", "content": "Say hi"}] + + # Prepare call arguments + call_args = { + "messages": messages, + "max_tokens": 100, + } + + # Add any additional config from subclass + call_args.update(request_params) + + # Call the handler + response = await litellm.anthropic.messages.acreate(**call_args) + + print(f"Response for {request_params['model']}: {json.dumps(response, indent=2, default=str)}") + + # Verify response structure + assert "content" in response, "Response should have 'content' field" + assert len(response["content"]) > 0, "Response content should not be empty" + + # Get the first content block + block = response["content"][0] + + # Check that the block is a dict, not a Pydantic object + assert isinstance(block, dict), ( + f"Content block should be a dict, but got {type(block)}. " + f"This means response format is inconsistent across providers." + ) + + # Verify we can access fields using dict syntax (not object attributes) + try: + block_type = block["type"] + print(f"✓ Successfully accessed block['type']: {block_type}") + except TypeError as e: + pytest.fail( + f"Cannot access content block using dict syntax: {e}. " + f"Block type: {type(block)}" + ) + + # Verify the block has expected structure + assert "type" in block, "Content block should have 'type' field" + if block["type"] == "text": + assert "text" in block, "Text content block should have 'text' field" + + print(f"✓ Response format consistency test passed for {request_params['model']}") + @pytest.mark.asyncio async def test_anthropic_messages_litellm_router_streaming_with_logging(self): """ diff --git a/tests/pass_through_unit_tests/test_anthropic_messages_passthrough.py b/tests/pass_through_unit_tests/test_anthropic_messages_passthrough.py index 17e72f29152..0a581fb512d 100644 --- a/tests/pass_through_unit_tests/test_anthropic_messages_passthrough.py +++ b/tests/pass_through_unit_tests/test_anthropic_messages_passthrough.py @@ -876,4 +876,4 @@ def test_sync_openai_messages(): assert response is not None assert isinstance(response, dict) - assert response["content"][0].text is not None + assert response["content"][0]["text"] is not None diff --git a/tests/test_litellm/llms/anthropic/experimental_pass_through/adapters/test_anthropic_experimental_pass_through_adapters_transformation.py b/tests/test_litellm/llms/anthropic/experimental_pass_through/adapters/test_anthropic_experimental_pass_through_adapters_transformation.py index 6a5c022ac7a..b228a51447b 100644 --- a/tests/test_litellm/llms/anthropic/experimental_pass_through/adapters/test_anthropic_experimental_pass_through_adapters_transformation.py +++ b/tests/test_litellm/llms/anthropic/experimental_pass_through/adapters/test_anthropic_experimental_pass_through_adapters_transformation.py @@ -341,10 +341,10 @@ def test_translate_openai_content_to_anthropic_empty_function_arguments(): result = adapter._translate_openai_content_to_anthropic(choices=openai_choices) assert len(result) == 1 - assert result[0].type == "tool_use" - assert result[0].id == "call_empty_args" - assert result[0].name == "test_function" - assert result[0].input == {}, "Empty function arguments should result in empty dict" + assert result[0]["type"] == "tool_use" + assert result[0]["id"] == "call_empty_args" + assert result[0]["name"] == "test_function" + assert result[0]["input"] == {}, "Empty function arguments should result in empty dict" def test_translate_openai_content_to_anthropic_text_and_tool_calls(): @@ -372,12 +372,12 @@ def test_translate_openai_content_to_anthropic_text_and_tool_calls(): result = adapter._translate_openai_content_to_anthropic(choices=openai_choices) assert len(result) == 2 - assert result[0].type == "text" - assert result[0].text == "Calling get_weather now." - assert result[1].type == "tool_use" - assert result[1].id == "call_weather" - assert result[1].name == "get_weather" - assert result[1].input == {"location": "Boston"} + assert result[0]["type"] == "text" + assert result[0]["text"] == "Calling get_weather now." + assert result[1]["type"] == "tool_use" + assert result[1]["id"] == "call_weather" + assert result[1]["name"] == "get_weather" + assert result[1]["input"] == {"location": "Boston"} def test_translate_openai_response_to_anthropic_text_and_tool_calls(): @@ -414,11 +414,11 @@ def test_translate_openai_response_to_anthropic_text_and_tool_calls(): anthropic_content = anthropic_response.get("content") assert anthropic_content is not None assert len(anthropic_content) == 2 - assert cast(Any, anthropic_content[0]).type == "text" - assert cast(Any, anthropic_content[0]).text == "Let me grab the current weather." - assert cast(Any, anthropic_content[1]).type == "tool_use" - assert cast(Any, anthropic_content[1]).id == "call_tool_combo" - assert cast(Any, anthropic_content[1]).input == {"location": "Paris"} + assert anthropic_content[0]["type"] == "text" + assert anthropic_content[0]["text"] == "Let me grab the current weather." + assert anthropic_content[1]["type"] == "tool_use" + assert anthropic_content[1]["id"] == "call_tool_combo" + assert anthropic_content[1]["input"] == {"location": "Paris"} assert anthropic_response.get("stop_reason") == "tool_use" @@ -484,11 +484,11 @@ def test_translate_openai_content_to_anthropic_thinking_and_redacted_thinking(): result = adapter._translate_openai_content_to_anthropic(choices=openai_choices) assert len(result) == 2 - assert result[0].type == "thinking" - assert result[0].thinking == "I need to summar" - assert result[0].signature == "sigsig" - assert result[1].type == "redacted_thinking" - assert result[1].data == "REDACTED" + assert result[0]["type"] == "thinking" + assert result[0]["thinking"] == "I need to summar" + assert result[0]["signature"] == "sigsig" + assert result[1]["type"] == "redacted_thinking" + assert result[1]["data"] == "REDACTED" def test_translate_streaming_openai_chunk_to_anthropic_with_thinking(): @@ -1443,13 +1443,13 @@ def test_translate_openai_content_to_anthropic_reasoning_content_without_thinkin assert len(result) == 2 # First block should be thinking block with reasoning_content - assert result[0].type == "thinking" - assert "Considering Letter Frequency" in result[0].thinking - assert "Calculating the Count" in result[0].thinking - assert result[0].signature is None + assert result[0]["type"] == "thinking" + assert "Considering Letter Frequency" in result[0]["thinking"] + assert "Calculating the Count" in result[0]["thinking"] + assert result[0]["signature"] is None # Second block should be text block with content - assert result[1].type == "text" - assert result[1].text == "There are **3** \"r\"s in the word strawberry." + assert result[1]["type"] == "text" + assert result[1]["text"] == "There are **3** \"r\"s in the word strawberry." def test_translate_streaming_openai_chunk_to_anthropic_reasoning_content_without_thinking_blocks(): @@ -1522,13 +1522,13 @@ def test_translate_openai_response_to_anthropic_with_reasoning_content_only(): assert len(anthropic_content) == 2 # First block should be thinking - assert cast(Any, anthropic_content[0]).type == "thinking" - assert "Considering Letter Frequency" in cast(Any, anthropic_content[0]).thinking - assert cast(Any, anthropic_content[0]).signature is None + assert anthropic_content[0]["type"] == "thinking" + assert "Considering Letter Frequency" in anthropic_content[0]["thinking"] + assert anthropic_content[0].get("signature") is None # Second block should be text - assert cast(Any, anthropic_content[1]).type == "text" - assert cast(Any, anthropic_content[1]).text == "There are **3** \"r\"s in the word strawberry." + assert anthropic_content[1]["type"] == "text" + assert anthropic_content[1]["text"] == "There are **3** \"r\"s in the word strawberry." assert anthropic_response.get("stop_reason") == "end_turn" @@ -1702,7 +1702,7 @@ def test_translate_openai_response_restores_tool_names(): ) # Find the tool_use block in the response - tool_use_blocks = [c for c in result["content"] if getattr(c, "type", None) == "tool_use"] + tool_use_blocks = [c for c in result["content"] if c.get("type") == "tool_use"] assert len(tool_use_blocks) == 1 # Name should be restored to original - assert getattr(tool_use_blocks[0], "name", None) == original_name + assert tool_use_blocks[0]["name"] == original_name From 15b717c3005ddecc50cb2d0b17c7d80365d08145 Mon Sep 17 00:00:00 2001 From: Ishaan Jaff Date: Wed, 4 Feb 2026 18:38:53 -0800 Subject: [PATCH 11/21] [Feat] UI - Add support for MCP Semantic Filtering on UI (#20454) * feat: remove_callbacks_by_type * feat: _init_semantic_filter_settings_in_db * add MCP semantic filtering settings endpoints * v0 - semantic filter UI * fix endpint _init_semantic_filter_settings_in_db * refactor ui * add LITELLM_UI_ALLOW_HEADERS * ui fix * ui fix --- litellm/constants.py | 5 + .../logging_callback_manager.py | 21 ++ litellm/proxy/agent_endpoints/a2a_routing.py | 2 +- litellm/proxy/proxy_server.py | 89 +++++ litellm/proxy/route_llm_request.py | 5 +- .../proxy_setting_endpoints.py | 100 +++++- .../useMCPSemanticFilterSettings.ts | 19 ++ .../useUpdateMCPSemanticFilterSettings.ts | 25 ++ .../MCPSemanticFilterSettings.tsx | 312 ++++++++++++++++++ .../MCPSemanticFilterTestPanel.tsx | 164 +++++++++ .../semanticFilterTestUtils.ts | 95 ++++++ .../src/components/mcp_tools/mcp_servers.tsx | 5 + .../src/components/networking.tsx | 131 ++++++++ 13 files changed, 970 insertions(+), 3 deletions(-) create mode 100644 ui/litellm-dashboard/src/app/(dashboard)/hooks/mcpSemanticFilterSettings/useMCPSemanticFilterSettings.ts create mode 100644 ui/litellm-dashboard/src/app/(dashboard)/hooks/mcpSemanticFilterSettings/useUpdateMCPSemanticFilterSettings.ts create mode 100644 ui/litellm-dashboard/src/components/Settings/AdminSettings/MCPSemanticFilterSettings/MCPSemanticFilterSettings.tsx create mode 100644 ui/litellm-dashboard/src/components/Settings/AdminSettings/MCPSemanticFilterSettings/MCPSemanticFilterTestPanel.tsx create mode 100644 ui/litellm-dashboard/src/components/Settings/AdminSettings/MCPSemanticFilterSettings/semanticFilterTestUtils.ts diff --git a/litellm/constants.py b/litellm/constants.py index 444e78f8ed4..872ad899f84 100644 --- a/litellm/constants.py +++ b/litellm/constants.py @@ -81,6 +81,11 @@ MAX_MCP_SEMANTIC_FILTER_TOOLS_HEADER_LENGTH = int( os.getenv("MAX_MCP_SEMANTIC_FILTER_TOOLS_HEADER_LENGTH", 150) ) +LITELLM_UI_ALLOW_HEADERS = [ + "x-litellm-semantic-filter", + "x-litellm-semantic-filter-tools", +] + # Gemini model-specific minimal thinking budget constants DEFAULT_REASONING_EFFORT_MINIMAL_THINKING_BUDGET_GEMINI_2_5_FLASH = int( os.getenv("DEFAULT_REASONING_EFFORT_MINIMAL_THINKING_BUDGET_GEMINI_2_5_FLASH", 1) diff --git a/litellm/litellm_core_utils/logging_callback_manager.py b/litellm/litellm_core_utils/logging_callback_manager.py index 4f76a5bad03..435ae078a65 100644 --- a/litellm/litellm_core_utils/logging_callback_manager.py +++ b/litellm/litellm_core_utils/logging_callback_manager.py @@ -114,6 +114,27 @@ class LoggingCallbackManager: for c in remove_list: callback_list.remove(c) + def remove_callbacks_by_type(self, callback_list, callback_type): + """ + Remove all callbacks of a specific type from a callback list. + + Args: + callback_list: The list to remove callbacks from (e.g., litellm.callbacks) + callback_type: The class type to match (e.g., SemanticToolFilterHook) + + Example: + litellm.logging_callback_manager.remove_callbacks_by_type( + litellm.callbacks, SemanticToolFilterHook + ) + """ + if not isinstance(callback_list, list): + return + + remove_list = [c for c in callback_list if isinstance(c, callback_type)] + + for c in remove_list: + callback_list.remove(c) + def _add_string_callback_to_list( self, callback: str, parent_list: List[Union[CustomLogger, Callable, str]] ): diff --git a/litellm/proxy/agent_endpoints/a2a_routing.py b/litellm/proxy/agent_endpoints/a2a_routing.py index 8e4c705df21..cb277d44ee9 100644 --- a/litellm/proxy/agent_endpoints/a2a_routing.py +++ b/litellm/proxy/agent_endpoints/a2a_routing.py @@ -11,7 +11,7 @@ import litellm from litellm._logging import verbose_proxy_logger -async def route_a2a_agent_request(data: dict, route_type: str) -> Optional[Any]: +def route_a2a_agent_request(data: dict, route_type: str) -> Optional[Any]: """ Route A2A agent requests directly to litellm with injected API base. diff --git a/litellm/proxy/proxy_server.py b/litellm/proxy/proxy_server.py index b06071481eb..022626e2992 100644 --- a/litellm/proxy/proxy_server.py +++ b/litellm/proxy/proxy_server.py @@ -47,6 +47,7 @@ from litellm.constants import ( DEFAULT_SLACK_ALERTING_THRESHOLD, LITELLM_EMBEDDING_PROVIDERS_SUPPORTING_INPUT_ARRAY_OF_TOKENS, LITELLM_SETTINGS_SAFE_DB_OVERRIDES, + LITELLM_UI_ALLOW_HEADERS, ) from litellm.litellm_core_utils.litellm_logging import ( _init_custom_logger_compatible_class, @@ -1214,6 +1215,7 @@ app.add_middleware( allow_credentials=True, allow_methods=["*"], allow_headers=["*"], + expose_headers=LITELLM_UI_ALLOW_HEADERS, ) app.add_middleware(PrometheusAuthMiddleware) @@ -3920,6 +3922,93 @@ class ProxyConfig: prisma_client=prisma_client, proxy_config=self ) + if self._should_load_db_object(object_type="semantic_filter_settings"): + await self._init_semantic_filter_settings_in_db( + prisma_client=prisma_client + ) + + async def _init_semantic_filter_settings_in_db(self, prisma_client: PrismaClient): + """ + Initialize MCP semantic filter settings from database. + Called periodically (approximately every 10 seconds) by background task to hot-reload settings across all pods. + """ + import json + + import litellm + from litellm.proxy.hooks.mcp_semantic_filter import SemanticToolFilterHook + + try: + # Load litellm_settings from DB + config_record = await prisma_client.db.litellm_config.find_unique( + where={"param_name": "litellm_settings"} + ) + + if config_record is None or config_record.param_value is None: + return + + litellm_settings = config_record.param_value + if isinstance(litellm_settings, str): + litellm_settings = json.loads(litellm_settings) + + mcp_semantic_filter_config = litellm_settings.get( + "mcp_semantic_tool_filter", None + ) + + if mcp_semantic_filter_config is None: + return + + # Check if settings have changed (compare with in-memory state) + if hasattr(self, "_last_semantic_filter_config"): + if self._last_semantic_filter_config == mcp_semantic_filter_config: + # If hook is missing or router isn't built yet, reinitialize anyway + active_hooks = ( + litellm.logging_callback_manager.get_custom_loggers_for_type( + SemanticToolFilterHook + ) + ) + if active_hooks: + for active_hook in active_hooks: + if isinstance(active_hook, SemanticToolFilterHook): + if ( + active_hook.filter is not None + and active_hook.filter.tool_router is not None + ): + verbose_proxy_logger.debug( + "Semantic filter settings unchanged, skipping reinitialization" + ) + return + verbose_proxy_logger.info( + "Semantic filter settings unchanged, but hook is missing or uninitialized. Reinitializing." + ) + + # Remove old hooks using logging callback manager + litellm.logging_callback_manager.remove_callbacks_by_type( + litellm.callbacks, SemanticToolFilterHook + ) + + # Initialize new hook if enabled + if mcp_semantic_filter_config.get("enabled", False): + global llm_router + hook = await SemanticToolFilterHook.initialize_from_config( + config=mcp_semantic_filter_config, + llm_router=llm_router, + ) + if hook: + litellm.logging_callback_manager.add_litellm_callback(hook) + verbose_proxy_logger.info( + "MCP Semantic Filter reinitialized from DB" + ) + else: + verbose_proxy_logger.info("MCP Semantic Filter disabled") + + # Store current config for comparison next time + self._last_semantic_filter_config = mcp_semantic_filter_config.copy() + + except Exception as e: + verbose_proxy_logger.exception( + f"Error initializing semantic filter settings from DB: {e}" + ) + async def _init_sso_settings_in_db(self, prisma_client: PrismaClient): """ Initialize SSO settings from database into the router on startup. diff --git a/litellm/proxy/route_llm_request.py b/litellm/proxy/route_llm_request.py index 39ef5fdd1d5..92fb88f7147 100644 --- a/litellm/proxy/route_llm_request.py +++ b/litellm/proxy/route_llm_request.py @@ -332,7 +332,10 @@ async def route_request( route_a2a_agent_request, ) - return await route_a2a_agent_request(data, route_type) + result = route_a2a_agent_request(data, route_type) + if result is not None: + return result + # Fall through to raise exception below if result is None elif user_model is not None: return getattr(litellm, f"{route_type}")(**data) diff --git a/litellm/proxy/ui_crud_endpoints/proxy_setting_endpoints.py b/litellm/proxy/ui_crud_endpoints/proxy_setting_endpoints.py index 30ec0766dbf..a308d0b2703 100644 --- a/litellm/proxy/ui_crud_endpoints/proxy_setting_endpoints.py +++ b/litellm/proxy/ui_crud_endpoints/proxy_setting_endpoints.py @@ -98,6 +98,40 @@ ALLOWED_UI_SETTINGS_FIELDS = { } +class MCPSemanticFilterSettings(BaseModel): + """Configuration for MCP Semantic Tool Filter""" + + enabled: bool = Field( + default=False, + description="Enable semantic filtering of MCP tools based on query relevance", + ) + + embedding_model: str = Field( + default="text-embedding-3-small", + description="Embedding model to use for semantic similarity (e.g., 'text-embedding-3-small', 'text-embedding-ada-002')", + ) + + top_k: int = Field( + default=10, + description="Number of most relevant tools to return", + ge=1, + le=100, + ) + + similarity_threshold: float = Field( + default=0.3, + description="Minimum similarity score for tool inclusion (0.0 to 1.0, where 1.0 = exact match)", + ge=0.0, + le=1.0, + ) + + +class MCPSemanticFilterSettingsResponse(SettingsResponse): + """Response model for MCP semantic filter settings""" + + pass + + @router.get( "/get/allowed_ips", tags=["Budget & Spend Tracking"], @@ -325,7 +359,7 @@ async def update_default_team_member_budget( async def _update_litellm_setting( - settings: Union[DefaultInternalUserParams, DefaultTeamSSOParams], + settings: Union[DefaultInternalUserParams, DefaultTeamSSOParams, MCPSemanticFilterSettings], settings_key: str, in_memory_var: Any, success_message: str, @@ -769,6 +803,70 @@ async def update_ui_theme_settings(theme_config: UIThemeConfig): } +@router.get( + "/get/mcp_semantic_filter_settings", + tags=["Settings"], + dependencies=[Depends(user_api_key_auth)], + response_model=MCPSemanticFilterSettingsResponse, +) +async def get_mcp_semantic_filter_settings( + user_api_key_dict: UserAPIKeyAuth = Depends(user_api_key_auth), +): + """ + Get MCP semantic filter configuration. + Returns current settings for semantic tool filtering. + """ + from litellm.proxy.proxy_server import prisma_client, proxy_config + + if prisma_client is None: + raise HTTPException( + status_code=500, + detail={"error": "Database not connected. Please connect a database."}, + ) + + config = await proxy_config.get_config() + + return await _get_settings_with_schema( + settings_key="mcp_semantic_tool_filter", + settings_class=MCPSemanticFilterSettings, + config=config, + ) + + +@router.patch( + "/update/mcp_semantic_filter_settings", + tags=["Settings"], + dependencies=[Depends(user_api_key_auth)], +) +async def update_mcp_semantic_filter_settings( + settings: MCPSemanticFilterSettings, + user_api_key_dict: UserAPIKeyAuth = Depends(user_api_key_auth), +): + """ + Update MCP semantic filter settings in database. + Settings will be picked up by all pods within approximately 10 seconds via background polling. + """ + result = await _update_litellm_setting( + settings=settings, + settings_key="mcp_semantic_tool_filter", + in_memory_var=None, + success_message="MCP Semantic Filter settings updated successfully. Changes will be applied across all pods within 10 seconds.", + ) + try: + from litellm.proxy.proxy_server import prisma_client, proxy_config + + if prisma_client is not None: + await proxy_config._init_semantic_filter_settings_in_db( + prisma_client=prisma_client + ) + except Exception as e: + verbose_proxy_logger.warning( + f"Failed to reinitialize MCP semantic filter settings immediately: {e}" + ) + + return result + + @router.get( "/in_product_nudges", tags=["UI Settings"], diff --git a/ui/litellm-dashboard/src/app/(dashboard)/hooks/mcpSemanticFilterSettings/useMCPSemanticFilterSettings.ts b/ui/litellm-dashboard/src/app/(dashboard)/hooks/mcpSemanticFilterSettings/useMCPSemanticFilterSettings.ts new file mode 100644 index 00000000000..e91f5aa670b --- /dev/null +++ b/ui/litellm-dashboard/src/app/(dashboard)/hooks/mcpSemanticFilterSettings/useMCPSemanticFilterSettings.ts @@ -0,0 +1,19 @@ +import { getMCPSemanticFilterSettings } from "@/components/networking"; +import { useQuery } from "@tanstack/react-query"; +import { createQueryKeys } from "../common/queryKeysFactory"; +import useAuthorized from "../useAuthorized"; + +const mcpSemanticFilterSettingsKeys = createQueryKeys( + "mcpSemanticFilterSettings" +); + +export const useMCPSemanticFilterSettings = () => { + const { accessToken } = useAuthorized(); + return useQuery>({ + queryKey: mcpSemanticFilterSettingsKeys.list({}), + queryFn: async () => await getMCPSemanticFilterSettings(accessToken), + enabled: !!accessToken, + staleTime: 60 * 60 * 1000, // 1 hour + gcTime: 60 * 60 * 1000, // 1 hour + }); +}; diff --git a/ui/litellm-dashboard/src/app/(dashboard)/hooks/mcpSemanticFilterSettings/useUpdateMCPSemanticFilterSettings.ts b/ui/litellm-dashboard/src/app/(dashboard)/hooks/mcpSemanticFilterSettings/useUpdateMCPSemanticFilterSettings.ts new file mode 100644 index 00000000000..2062b4f4c29 --- /dev/null +++ b/ui/litellm-dashboard/src/app/(dashboard)/hooks/mcpSemanticFilterSettings/useUpdateMCPSemanticFilterSettings.ts @@ -0,0 +1,25 @@ +import { updateMCPSemanticFilterSettings } from "@/components/networking"; +import { useMutation, useQueryClient } from "@tanstack/react-query"; +import { createQueryKeys } from "../common/queryKeysFactory"; + +const mcpSemanticFilterSettingsKeys = createQueryKeys( + "mcpSemanticFilterSettings" +); + +export const useUpdateMCPSemanticFilterSettings = (accessToken: string) => { + const queryClient = useQueryClient(); + + return useMutation({ + mutationFn: async (settings: Record) => { + if (!accessToken) { + throw new Error("Access token is required"); + } + return updateMCPSemanticFilterSettings(accessToken, settings); + }, + onSuccess: () => { + queryClient.invalidateQueries({ + queryKey: mcpSemanticFilterSettingsKeys.all, + }); + }, + }); +}; diff --git a/ui/litellm-dashboard/src/components/Settings/AdminSettings/MCPSemanticFilterSettings/MCPSemanticFilterSettings.tsx b/ui/litellm-dashboard/src/components/Settings/AdminSettings/MCPSemanticFilterSettings/MCPSemanticFilterSettings.tsx new file mode 100644 index 00000000000..6e669f74ab3 --- /dev/null +++ b/ui/litellm-dashboard/src/components/Settings/AdminSettings/MCPSemanticFilterSettings/MCPSemanticFilterSettings.tsx @@ -0,0 +1,312 @@ +"use client"; + +import { useMCPSemanticFilterSettings } from "@/app/(dashboard)/hooks/mcpSemanticFilterSettings/useMCPSemanticFilterSettings"; +import { useUpdateMCPSemanticFilterSettings } from "@/app/(dashboard)/hooks/mcpSemanticFilterSettings/useUpdateMCPSemanticFilterSettings"; +import NotificationManager from "@/components/molecules/notifications_manager"; +import { + Alert, + Button, + Card, + Col, + Form, + InputNumber, + Row, + Select, + Skeleton, + Slider, + Space, + Switch, + Typography, + Tooltip, +} from "antd"; +import { QuestionCircleOutlined, CheckCircleOutlined, SaveOutlined } from "@ant-design/icons"; +import { useEffect, useState } from "react"; +import { fetchAvailableModels, ModelGroup } from "@/components/playground/llm_calls/fetch_models"; +import MCPSemanticFilterTestPanel from "./MCPSemanticFilterTestPanel"; +import { getCurlCommand, runSemanticFilterTest, TestResult } from "./semanticFilterTestUtils"; + +interface MCPSemanticFilterSettingsProps { + accessToken: string | null; +} + +export default function MCPSemanticFilterSettings({ accessToken }: MCPSemanticFilterSettingsProps) { + const { data, isLoading, isError, error } = useMCPSemanticFilterSettings(); + const { + mutate: updateSettings, + isPending: isUpdating, + error: updateError, + } = useUpdateMCPSemanticFilterSettings(accessToken || ""); + const [form] = Form.useForm(); + const [saveSuccess, setSaveSuccess] = useState(false); + const [isDirty, setIsDirty] = useState(false); + const [embeddingModels, setEmbeddingModels] = useState([]); + const [loadingModels, setLoadingModels] = useState(true); + + // Test section state + const [testQuery, setTestQuery] = useState(""); + const [testModel, setTestModel] = useState("gpt-4o"); + const [testResult, setTestResult] = useState(null); + const [isTesting, setIsTesting] = useState(false); + const [showCurl, setShowCurl] = useState(false); + + const schema = data?.field_schema; + const values = data?.values ?? {}; + + useEffect(() => { + const loadEmbeddingModels = async () => { + if (!accessToken) return; + try { + setLoadingModels(true); + const models = await fetchAvailableModels(accessToken); + const embeddingOnly = models.filter((model) => model.mode === "embedding"); + setEmbeddingModels(embeddingOnly); + } catch (error) { + console.error("Error fetching embedding models:", error); + } finally { + setLoadingModels(false); + } + }; + + loadEmbeddingModels(); + }, [accessToken]); + + useEffect(() => { + if (values) { + form.setFieldsValue({ + enabled: values.enabled ?? false, + embedding_model: values.embedding_model ?? "text-embedding-3-small", + top_k: values.top_k ?? 10, + similarity_threshold: values.similarity_threshold ?? 0.3, + }); + setIsDirty(false); + } + }, [values, form]); + + const handleSave = async () => { + try { + const formValues = await form.validateFields(); + updateSettings(formValues, { + onSuccess: () => { + setIsDirty(false); + setSaveSuccess(true); + setTimeout(() => setSaveSuccess(false), 3000); + NotificationManager.success( + "Settings updated successfully. Changes will be applied across all pods within 10 seconds." + ); + }, + onError: (error) => { + NotificationManager.fromBackend(error); + }, + }); + } catch (error) { + console.error("Form validation failed:", error); + } + }; + + const handleTest = async () => { + if (!accessToken) { + return; + } + + await runSemanticFilterTest({ + accessToken, + testModel, + testQuery, + setIsTesting, + setTestResult, + }); + }; + + if (!accessToken) { + return ( +
+ Please log in to configure semantic filter settings. +
+ ); + } + + return ( +
+ {isLoading ? ( + + ) : isError ? ( + + ) : ( + <> + + + {saveSuccess && ( + } + showIcon + closable + style={{ marginBottom: 16 }} + /> + )} + + {updateError && ( + + )} + + + {/* Left Column - Settings */} +
+ { + setIsDirty(true); + }} + > + + + Enable Semantic Filtering + + + + + } + valuePropName="checked" + > + + + + + {schema?.properties?.enabled?.description} + + + + + + Embedding Model + + + + + } + > +
-gWPd>|tj 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 literal 0 HcmV?d00001 diff --git a/docs/my-website/img/okta_client_credentials.png b/docs/my-website/img/okta_client_credentials.png new file mode 100644 index 0000000000000000000000000000000000000000..a00a9f4657e23e0fa80fb430b05165fe10db646c GIT binary patch literal 65238 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 bo0q%hg##;TfzG)tT)?omIgNa6<&*S3CoDHF literal 0 HcmV?d00001 From 47b546f69a7454e7049f88ee5d491e5df2b9819f Mon Sep 17 00:00:00 2001 From: jquinter Date: Wed, 4 Feb 2026 23:41:01 -0300 Subject: [PATCH 13/21] fix(lint): remove unused Any/cast imports in github_copilot transformation (#20431) The cast(Any, message) pattern was used to suppress typed-dict mutation warnings, but the parameter has no type annotation so it's unnecessary. Direct assignment works and eliminates the F401 unused-import lint error. Co-authored-by: Claude Opus 4.5 --- litellm/llms/github_copilot/chat/transformation.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/litellm/llms/github_copilot/chat/transformation.py b/litellm/llms/github_copilot/chat/transformation.py index 945b7ebf7ff..d613c82402d 100644 --- a/litellm/llms/github_copilot/chat/transformation.py +++ b/litellm/llms/github_copilot/chat/transformation.py @@ -1,4 +1,4 @@ -from typing import Any, List, Optional, Tuple, cast +from typing import List, Optional, Tuple from litellm.exceptions import AuthenticationError from litellm.llms.openai.openai import OpenAIConfig @@ -54,7 +54,7 @@ class GithubCopilotConfig(OpenAIConfig): # GitHub Copilot API now supports system prompts for all models (Claude, GPT, etc.) # No conversion needed - just return messages as-is return messages - + # Default behavior: convert system messages to assistant for compatibility transformed_messages = [] for message in messages: @@ -65,7 +65,7 @@ class GithubCopilotConfig(OpenAIConfig): transformed_messages.append(transformed_message) else: transformed_messages.append(message) - + return transformed_messages def validate_environment( From e0802783f3957a822603b5a4893a2e153dc28e52 Mon Sep 17 00:00:00 2001 From: Cesar Garcia <128240629+Chesars@users.noreply.github.com> Date: Thu, 5 Feb 2026 00:35:22 -0300 Subject: [PATCH 14/21] feat(openrouter): add Qwen3-235B models (#20455) Add OpenRouter Qwen3-235B-A22B models to the pricing configuration: - openrouter/qwen/qwen3-235b-a22b-2507 - openrouter/qwen/qwen3-235b-a22b-thinking-2507 Closes request from PR #13019 comments. --- model_prices_and_context_window.json | 25 +++++++++++++++++++++++++ 1 file changed, 25 insertions(+) diff --git a/model_prices_and_context_window.json b/model_prices_and_context_window.json index 6d399d25bf6..d3038d13a1e 100644 --- a/model_prices_and_context_window.json +++ b/model_prices_and_context_window.json @@ -24419,6 +24419,31 @@ "supports_tool_choice": true, "supports_function_calling": true }, + "openrouter/qwen/qwen3-235b-a22b-2507": { + "input_cost_per_token": 7.1e-08, + "litellm_provider": "openrouter", + "max_input_tokens": 262144, + "max_output_tokens": 262144, + "max_tokens": 262144, + "mode": "chat", + "output_cost_per_token": 1e-07, + "source": "https://openrouter.ai/qwen/qwen3-235b-a22b-2507", + "supports_function_calling": true, + "supports_tool_choice": true + }, + "openrouter/qwen/qwen3-235b-a22b-thinking-2507": { + "input_cost_per_token": 1.1e-07, + "litellm_provider": "openrouter", + "max_input_tokens": 262144, + "max_output_tokens": 262144, + "max_tokens": 262144, + "mode": "chat", + "output_cost_per_token": 6e-07, + "source": "https://openrouter.ai/qwen/qwen3-235b-a22b-thinking-2507", + "supports_function_calling": true, + "supports_reasoning": true, + "supports_tool_choice": true + }, "openrouter/switchpoint/router": { "input_cost_per_token": 8.5e-07, "litellm_provider": "openrouter", From 3c12dda8564c841881d0a728ad6e926ac0ee9d4f Mon Sep 17 00:00:00 2001 From: Sameer Kankute Date: Thu, 5 Feb 2026 09:21:20 +0530 Subject: [PATCH 15/21] =?UTF-8?q?bump:=20litellm-proxy-extras=200.4.29=20?= =?UTF-8?q?=E2=86=92=200.4.30?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - Add allow_team_guardrail_config field to TeamTable and DeletedTeamTable - Add migration 20260205091235_allow_team_guardrail_config --- ...litellm_proxy_extras-0.4.30-py3-none-any.whl | Bin 0 -> 51217 bytes .../dist/litellm_proxy_extras-0.4.30.tar.gz | Bin 0 -> 23752 bytes .../migration.sql | 6 ++++++ litellm-proxy-extras/pyproject.toml | 4 ++-- pyproject.toml | 2 +- requirements.txt | 2 +- schema.prisma | 2 ++ 7 files changed, 12 insertions(+), 4 deletions(-) create mode 100644 litellm-proxy-extras/dist/litellm_proxy_extras-0.4.30-py3-none-any.whl create mode 100644 litellm-proxy-extras/dist/litellm_proxy_extras-0.4.30.tar.gz create mode 100644 litellm-proxy-extras/litellm_proxy_extras/migrations/20260205091235_allow_team_guardrail_config/migration.sql diff --git a/litellm-proxy-extras/dist/litellm_proxy_extras-0.4.30-py3-none-any.whl b/litellm-proxy-extras/dist/litellm_proxy_extras-0.4.30-py3-none-any.whl new file mode 100644 index 0000000000000000000000000000000000000000..383f9b7b43ffce0cbeb9041dd657e016abc1e1db GIT binary patch literal 51217 zcmcG$1yq%5*EUL*2nYx$DJ9LKK|~q>>6FezcSuW1Bi$k0ol18%(g;!l(v5(eXQ_LC zAH4fLKl}XSIL5skGGvT3=RM<^*PQc~c?AoH4Fv^-1e_o~eKSi#Lt_g= z;P-vyCEw4IU^HAPlVpC@?O8<>>P_<-c%y7=BWkG#E<2gZT5W?VAIRTy-_;KP0Mmxge#=hem(?QS7BG zGnuGo!X>H{D__%BnR^L- zuV4kkCQ9)u9ZW>{zN8#4PQ&1X>C>~Tj*jCH$TYDl>1ZF%%~qB4=reoB{fL3e5~}#% zGHNZn^OBD>vZn$O3jLUBBDJidHRl}pLmUupWR?qP-g^~dtWbxHrTulm<{E~oO38uVH@ zMxwHw5_b~@#SF|&w{i_OrM0(U>7}SvZnMf6Xb|clUihvooFU^m&5SL;jDPh zRn>XRS#}KfA+0AXS!iLX@Fx>I)YWp1idzyfeh9)(hB3EG!-Yc96ZPAEp2{wyi>gK~ zS6btcK$8+V)t4*~zOSzZb;7}*Xq2LS?U^c*m}FKz9IXzP$Covlo&2)OKE;z+#*D_@5!Ll;9G94 zkHh7g4s`;d1avsQ5@e5WvI>$!gc0wZ2K3F>(-EI{_KP(a+e^B*bW} zi|IziE=&TxO;rs;yhR;M*X}uO9WME?olO#lw8yOrwVN)jPH_nuNTiy5QEsv#>My2H zUaLG;wxykgdk|RXiQ8fXAFxz#>am{u(u#@_Y^;yY4;`{;D=mTH;}n2${E=;)ru`?6 z{*uPvw`#C>rfNkJIyw&j(EBh?#{#OaY-{=!YWOc7x!Tu@>Xig0Lqpd}JoyT1)z?S` z3nIpb4ZAnf8!o?PZE6f>3Nv~H9m)5){$xkhGkZC%Myv7dS+kSdAn2Zkg>Ni!T@r3E z6pE9LA-o3&MvBxQjtf)vs zyifQ|S8(mo8vU#zp9Wp)^Y^~4L8B>pue(_7OxT~xiMl6P7%=D}gz74R(Nmt^-jb=) zhO1OZ2-Rg;Ig%FT8G+i2DM}iZEpg~49wNd9!6Emfb_Mq4ptxYwZag!9n$*T0_2OGACyX?i zOc95#VY8<4AdW3%%SRz;^$?v0({vt&>bT7))QlWdWpSJDKPsITHW0zL9CdD@7|e4? z>klS!6UScifO9(EscoV3S=ip?#g=b=ZTRKOhf;lktk+%{KAU3~!OwlT?2LxQs7c0! zKbnL6!f9T0^7G2Jxj)gWx*yx{W4rRj!)1K0nt;Ieg>38!)Tk;xXxN|XL?cB-QZao%Q=vw!Y;_P7A%TnJ2U&>@?K(=Q%GV?-NvhfJ zMr-{15+{qL)cesLNj`>pLg9w3#u4SNOuDl7wpqqbxRh^# ziD6Lw^!DJh4cF9A#kyl&1zOb_!2_ZQal^;?G!cUZMl#*elX{tk>KPKtyZ&of=GY6i z%GBP1kFtpNSTe^fNR(IdZB3`&%hdSUe$C@hc)0PtjG{xmdM?FqUYfm zoZ#*B{R{ufXFFz*Ie6a$4L@ml=}9*F#OrQbi(cpZi5i6p7N3S` z_X=hdeYBK9p_u{MMk`I)F`}5Npsz$b!jsJMsxRi)wN9_ORFh?*3GQPOR&|hbNYey# zbRPD-To{Vk%Qf$-IZ_m`-QLM4H9GxJf6qkqe1}S3p3uc!E}gulkGv@8NnXH&x=5kOqB|0Z>EFo8hKS~~jrTKYQ1W=>l6wqP4AI~`rKTWK^|Ud_}Sgy(ju z43|nb#Wb~?l4L+eXM#&sDcwS^BiaC0m2q_%)XCXd8HoaYZt<-ysbU_c>4C~qqZ3V} zzNf<(7&5!ag4)aVSa^PP-3Ln%)#+lHxwZER?&S^*erEJ_K}mnzfUT!ID@_wY&-Jl2 z;Z&d5@TGOULkt^k$3xr;v(3nH=!~o7@i+E8f$93?c}+G930iN#bl|Q}KdAC25UA4k z;3M*$AuU$K>Z0sO@;ub^XDBH+<|@*BjgfOD-~ji7ir<5>zAzLIcz3A`t0rhN{T!+X&=^IUae z!U|DQJ?XxK40iLCZc8IeM@Yr}ahw>WHKUlhK&Asr_+XvQB2hB1GRY&Gg}_X)pS+D=2j{wn@_LUJ+CWe)DFiivar2uJkn@DN3E{+ zG5Xc%K=lqO9XCdt&X)_vcsf`on<58C^~U&0DkRTM7|*6)jSaP?egYw6Bbxix$2HTM@JIn9Ao3XG`4t11+&P4k{orUl8_&s#*69bGucb{|Htpvd#&%Na4t+s+F z@$1vEsfGCg({l6PAh;Ckr!>Ne!3Cy9h6{A^#9k>MKXyj=Ff944OwiGqj>y<57NPF? zaZf~DQLlW7(igT^U;93AwEC74n|-o%VlR-beU^oM%e7zYrZO%2y9u2DC6)sRVmSX; zxcv=}|3c6#Ow3GdtZeLBKwYP2s%2}hrw6vR)zY!h*D?Tt0$Bfltmt=;&@nXpCtZgG z|FR&yQ`e60X|K95<8-7+>?7vb8O=0|z_o~$rkY}@#^Zg>F{o_Pc)ypJ-t9jTf?pnJ z8&eC6pIE#e<<4KZke}#*d4`x1s*ArEl+3{>pSr3j9Hd%{a1y(X_3Rx+K=V0^i0;&G zzh$94fv|n?MoCLc9QsWqBq-rCp8>*K10}5dU6sJf^h*gWOuszGT*pGk5Rlsdkp7<} zO%7+W1boHU;W{ufM~GDZB_&qy$`a@JM^TUp0{#lSPp%}zkKIHBUr(BF)mNIXsS7U7 zvE*TmF0;;+7rl`Rw(khS=*baj1ixqXOBk5C99TTe#}|1*I!ySO0DeUcF500c%I1yB zbzvKmqhaVgIt#*aTi?&m#HuJm!o@i6+s~I=!GqPt0&YL>Jki`-4b5`ANSEQu&9Hbn z9MEE1JH!LRVpMH?*QD+n<8u^&$avz`^7#gQTK7#P4%eEf%qqL%zO*FllKjY{rrb{o z(>GEZAJp=zenp`vjwV2V{zl+DO<@dw)kIfvq(nH_@2tSZYSR6qJM2wGXSDG-nE?uR z1dhVp70nFdWa40B(Xs>Um}{AX&2@o{V+FP`H@3C?Ro4A&pOEs6qK6+6l|;U}N$p3v zG0G_GVJXY|g5a~FhFj@iLc}93GCtS1YE62cWD8H2D+|)S;9Kt}ijkLJV+t%j?*anS zJACQohcBz$s0{`ZW6mZb z4bemT%g|a$FrbE$OKL&0?eoa+AwAKQ&i!y36cLy+G6a_{-**--JSOcw*er{G4OgKe zw}q8^$x6b+CbHFlM%^^ud)#RCh=QueXXta1&3w*bP_1w41P+GPWOGOQ8w4-oh8pbNq+AfC$YD|1aYAE)p z9fAC`Z*Zo(6lGZ_k8J!fEN=*Rh1dR(S5Tv}uzbG97b1=-D&~ajNAv|tEIRc+R%1I0 zu@$fpQzoDB5qS<_q!xIyxt0s~d3=_UewU+8F8qQwM+sK#LWg_!{yTP*u-y>yxuUnh zX-mZSOFHO$C_|kzb`y^h3L9Ky2a9|Bxnn?&k-3CcT0LIxbk=HJ4wMQ8r@dU~$}bs? z+OmO{{|;lma1W_k|D`-?Cb%o|zDTjJ!y^2S$4I$#8a)xKIhV}i)nH;oaWc#MHIeYM zgXG}%&%)lbbhrqHpDG1w;;?8VK+gw`(;6d;e)y;s9(D4wOZFgH1exdP@gSl0>FYK^ zMMT4*g8R&-pA4FU`*%OQqMYj#SMpQQ>e*uCI_)ht;98o}3D6)`Kust3AaTFizZ7 zI#}4L#@dhAaPAX?tr=U2H)GIw#@S@)J?B{U5{P}O z0@kGM4(9V5>^jefen@?$U<{1lFu&rB9VTi&)|u{iF$l^Ty9c_Tpk?dCi$+s|hb%uo zO?htp?8qt-gK-MMnpJjhd#&xTX0OCgYCw0r0`=2Q86!iU^SB_~K?KSn%qJnL`Fav^ zwRdd;2N#>RzOj_Z0eJ3xk01OHNfEIkj9l*+iJ^GCu--j<*ctqd5?LT=E@NSZh~5wW zHCMs=SJ(=eDW|WZL|Rg#jN)H>G%P|M!J7{II+5C{T6uf{fDbFhWoP4gN1 ztY}5u%edG7N~~zn2KfM8X79+>Iz&e1podQEcz-{{L9D+&4^>P8ok4WqRRE)y#QPzs zB8Bp`C74@={(S=A41sU!034Hl^Q}4Am{@;DHXSoFO9u!_vb47Y+iLvXO<`#^!e^z)RAxxbmMEC^nvHyb-#wE4JV%XJe#U-|a zCpg3;m09vxF=lCN37%KN9|h0^fl3>@01xY=IB3 z?M-2Q!v{>-Ko~x|&Vj;D@e}0V^H3L~SWs|x+Zam;RK<{P@|sZ$*OV+}dJb2rOpUoF z%&QbBg-II0np}J#?ZGxo@HQ}Q@kAk(K{C$V-bVbSY}N`=EVI_MLP7R?ZP!F)@Ithc z8zrI1n5uWG3d7-L?zC_Ni}`H4_2ZK-U+oC%t-hQ4z1&LJw6dV&Mc_Sh7bHaZZdQt& zQc(W-y0D`CP3OBa=GgjC35$q}qx$>L51uOByRTA&%~;7L|I}}O{ig$`wfXbqC-zC} zrRZO(ar1DfXoJLQV{m_*Ob?s|XkoL{#7dZd^|gF*ehg17MvQcha8t`Aw9~Q>Enfp# zzH^#j19331GqL@_1?GAXw+9G^e@YX{vXT(mq49!NvtB_*pv){bxttDGr4o~@FehyD zUZfa)gx#<^ub~>pD+d*l*l*vj#4$hMRK3ir;XzOUkvCU8%|)?ro{@N5&&;)hvy(y9Q@1CpBdCpScZBCbUNO z`ZYxdDCm;fI#jk$*-ebPCHFawHkccvV+zRKYNw7`nrPiwIZg8(#g5WkX*}ywp%Bv) zDR2}|ufiw{Ga)Sro?Uho8vDt(t9#jlZ~cjZhFVmqyJ;}99}z7@PM_-mz9Sgl|7|iI z+EN$E*{$mMn&N(Z9H3u9K)-r-wc@|@`x}HBfpyI6jI;nG3e~D|_aFfS_~##=a>3cwRO$%q(_(WYg^JpF`h+f_4x zu#gf<#JR$CSfX(8mWxxhj}4t1Y18A=H(ikn9p7w|h(>uO`;l%yVTzt4a4sYKp-ijbkJA`tlpM*o7O( ztejeWqea!rI3ehW=ge@a@p3HeO5qwg@#mtiA`Pqh5i#NT$YO%I2#9&z-Nu6CwyWmj z({t^5>DsV=HvlHZ-a(!pVf@o^{BhU z`eIm3nnnZ}lB4DOqqJaL1_s*7I9m%j~o^4lMr{=t3 zWhbHON2K)=&QW)`WvrXGm^Ohg2uVMZz`1h;$p+#CaWFH1SbnD=I~_awUl#qVo&uW6 zx9k}L75b^g=uyNZdc{_4j*zYI%OP3Y9at;=4HkZZg#8|AMkP5bJ8N01lT+m5V|gg( ztfh$d2)PfA{-#3yY`D0$kVD+JlC@6Yi?aYVk=ET!kc$bZi&)tpOskfzu_4e!x6?8J z(#!Aq=uc4yiHEo3_#Dvy_$9WlL(0-Sm6YZ@Bqs8QAyF*><2ECmFwrqBHL;5;^!3$n~Hkz+(Jn$!BTF|esW?4 zr@BE~&$U|@;eig^ln$<7Tw!DseZ8R&s*eEeZ0G&urC?#ddOH0Km#+Q?IIuixpLiEl z(WWPfLXt(}G?7@dH>1g3-*?kHhf#Ib1St|8{OH?xThvf9)MlK7wqxTxzwj|JOS^jS zeO=ux1|jH)!3pH<4S;iJ$jHV7Vq#@xV`aSsLjXY(}vbeXPA@3F)sfrN09r`~U*d zo!NH)J_2Ge1C{_`-wo|`Z1imawhb`l|773Y!ucU-@EyQn5_3_HkA-q)vEy&(ZY@2n z%n7642oruf(R#A`P3Rtdg{OLi->GB@qZr9{{Wi}`&7xR7mmpgALhqW(MOW7nc&Y-qlBV2hsZ?e`>P4~M`Dd> zBYiEXlOx=D1g&`noo*`26hMqDX0V@b{nG_Ui)LTd2E(N7wC~}h(!lGuf>kHs8rw6M z=36-RyRvS!GN9G8f791sV+Q`PfPgaeF9c_)YXV@nf6{D`+=vC>Rc_yCEgV~gQcl)V zXvTetu$5n>GiCFu;j(87FGjdt**`44)J{Z#PFd|20x{r1^lFy2{!Zx zoVVntzyr)ckP1bKINGR$an$|p)0QAn0y)m-E@iS}X_;~EGtK*P4n;J&@f5yiuU|z6 zfP2W~KC%sOpt?TiWBTfWCm6X=ILUHs8ll0!*!f&F=DSypAO00loB#4V`1JEcRqO>? z&X{b8tTdR%(Y%zIrkiz&pCtNZP3OrHv<)(}_?&gT%f1?8kG!QPT`)g5R{Cs9Kqw`S zLgeGvF3V|0^z7+ek1(SFsyu^KE=n6$#yx5L0NPsHx?-0Hgx2q1dS|zA&g*C{-q9gF zNNi?F@vtpz)U$tUfLE9~L(CFvyoafWl>5G`XiixcnTIaD2yt;-$Q6+(+PhX({5Uwl z_p&QgVQ1H@Yr(BnQZO0)7A=iC;zDEz_y_X8@(*CJ18{N>z{o=CD=iCqGczrq5Hz-P z`j4994l({lK`1Ndk!$@s%FED*Nhr%%{VE|3(Pj7U9q*T|Esau443D>~Z)L+!EV0OU zb8uC1Rv{JiWbq*vQr@0+`ZVq5Zv{x_3>0WV324qqC-T^vDB!i_@yp`RUKcru#pXri>s}^QrEIodJ zNm#JBw7G`2iIu*HhrNRLh|m-a|DfhSYi9rPeAyg8QVHNb@652X1EV^S$jzdqr(>(9 zqYq?1dwoN&9e_-AEDUdFyX5zOXS?i3wCA4k#*FV|ROL1og-F!PWPM1`>Kk~y+gtc2 zcaxGBpQ7@IUSXV)ou5RE5?HMcdo70xX!lBIDkwe6{}lWwq4WC)I%*~x7gEMOL#Ool z8eNrzgqZA6j@7S1EVFR@crca;T5jsSymlD)K|M->fiADh9C|0TnM8tAwabEqOXd`h zG3<-I`M7e=N&R*@qhAUmf`HO-*nguJpr&SK<7EDA2{+LCKV*U| z`94U&S${$6BaKEbvtIVJOIEF_oIw9kM5N487W+Qg6f?QIR!7+(Ns*YmCqrEYOTqkz zzE?d;6hfNPqt`@T#m%C%@`2%!^7o^D91tpGV=;OjXZucfmxXb?8KqqL5f*N2M&^kN zQ`S7^Kf3=QDwavVT!ssE^!3oeE+S;H=4aZds#)4Oq_SjYxkiPZSp+=`x%_WQpLm5#Zo>$5uIbU>Q5&@ zqYg8Vheg*P(5OqiNOvw+C7@QJ&a-~wf_PK8!X%3da)44HM9iI`GN4>$CKllH7S8`a zC-u8TN6G$I64H|Uzk(!mf&8t|2m$`1x)i<`ll~Z{3=FsM-m$rjAOx=J0_V=Kl><_= z0QT~`Du)!G#uf&aT6&gd_U3?<{I_!aF0$C8AxY8Gc<0OBl45Sf>#V=N(v@!a~O!Y-^>X z2N0rmmX>C}{(aNrJEDe6fS!Ek?hE1WJl|tv=kiVdZWB|oE&9x7{;W*=^W_&OA?}}E zp=T$S3p2)JT&^ZEvMgUvZAMAWph#&(88T9dWt@3{j1frmhe*Hpv#cH`zN^-SEm7$} z)K=%%f*q8|M}eb#fAxVJOMrPkZy$=+Da9QhzgB&bQdbh(&>W(1G(51C5kN5IiT5Gn zQo{omxCT{hAK>)6<6YfiJD-v}9X11Z<_6rK_?_<#=y?ON>rcDJ z)=uBp5@LrpFUwb^4=6h^>JJ|#YSwn6FXq7z^$Q?J2?-*3&S0RTkHO$BHx-0ig<+g> za#wJ(#K2cR%3Knj7WF1QC0#u7Ai^j_3|Rlxh}9`4$>IlPuVIBp`4%emiElnD^iHx< zg6DTaV=n?D?2%Uq(N}u2iG&>W&0Hh%{1wQ!^y`I ziu}_{i;vHSBhbS2K2ZQog3C*n(t?xsr5RRs7aVN*14#i4>S`BsYVJ4>Jk1egfROI`0^zoziTE?0}2za3g` z|5RnoO*30iqXQdXfy!}(z|8nKTe+($M9 zwvV)I_%HMhn{?VJL5%j2BBGKUEVXAuja&*MIIRSW$mn6}5t(!ihIDG_z4BO%F}X^8 zhCw99Xs5KJS;>i8S&dilJ*nNX-{0N}@3e#?vrvE%M}Pwf@qgd=|6YH%4d^*R>>w_n zlf?=&tso%~s9KD5e)CelSk_;0@K>1s2UHglCJjs}VYlzT4Sa%Bjd-s?$=T|7`e8bb zgw#NwcA*TEeyA0`Ixl8trAN;$7vo%1qc7w)U6_ z)IJ||8RQ2RoSs(}oicJn20poq(kf^MA$UU2C)-VQrP-|BW8_vbWA?CJ``2``>;uZ) zrc0>}e}3SzP_fUbdY1qJzW#1+PWC5Fk6?UT=NsKBd>EtPsa-?skn zM8dh{^>nn88xH$o47&Kyo|ae`b=4Z>4p-(EoJO#=w+Hj!Qy(GffaS2$CX|S>YNKHT zL?w@(scD?-iXrv7u?KLU+(b`TZt-R=$k-2a0qsx%7Agh&eJ2YA1~HhpSUG@kPkRf9 zh3aelZNoQ%R&-bkFmr?YZr3GnIMNHYB_n50@lj=>5#<*V!befjIMq^n+eQ9F*l@N# z8&|F)vzyI7Kp%I=wNeDak_=@+QA(0fE83>F*kyliarA3^+U4<$%Zx^)0F$Wg2-}tA z>;o)QcfL4^rT{~AeGF1^H5q+`bWYB!e1IuFA)ae+WfDK2~TesiU(wxYQBVX?#hd@D5jRR*C4O9r4;-4I^ePM zAr_2&Zq#-)qAsR6uXi+x%i=oilhDDfr-b(DuIF;D^-aC}ZwM<9CS}`#v|ie2;rHZY zf2cwz>UwPtS0($HGNFR>Eo0(==PRKL53`Dc8ep;OsoUipY&(e%CZ?9xWU4eij|;Z= z@8at@bU`~`pP_B$e_?;&98Ikid{$Ofwf{i!uuqv8nmoq3w?xxlz{fUw_|p2t3zbv} zV{VQ3fbZFsL+k0bR!JTToIM88Ee)7GzEH(SRhxdTKb}8$QMGp6+5ji^Q30k)ecrHW zR{HxT^Mj|a3x_e4jNbI|?0Fdu-4pZ)2}tlR>UB0AA~HZ}-yLg<`nl~SDP!q!O7#$< zX>a5z#?k{$XwjLJ#F9BEg}6TZvxNmVUhO~x$YA-y^Nd(9*=tORmgC!_0r|)Gf9wFZ zh5}p=q$<5j^kf1tvjBuW=N}Mg3)ZpGGx}ZN{DUL8h4Wapk>L3_yzQW+R13@rP4*Y0 zPz{#9R28Qb(#=;rjx|#ThMTBun8}O6<90>}=O~afGb$*6df$Dyy!Q%E;E?loILn78cNL5u8cdi|5Qobr*b@jmQ~rr`ivmo-tRuLc0vIR z8y3p-ZZ|6NPGYNOQ1Av>{T`W6javu#TXOP`5+t8`-83kvq8;hEkgAsbqN8TtNQw@8 z?sXiwB5xWxyEO)cb5=1s1!z?p(C%HyL7Wn9v6Df!TA7Wnv> z2qf@eA+6v1(1J78<>%(D*>u@Wb=Ub9PMUFk=~P-LwJ&a`is#3L(Omb)re<`j6KA zF_Ti!#r%^uzUFGfcDP_0a8H-xldE6Lk`&2SKc7J$wih8j1<$mXU`qKq8zsWbD6p0b zI`bN*)Za8B`{|=;NWlxi(Q3fCQ>cfCJVKR%1Q!TgfQWZDu>il|U}0nV&A|QHi~)K{5JdE6IvE&0 z{MA3cd1ZHy>{ff}<`_ZxcDNxgG_SnLIv^DC5}d4zC4a$ zRd<~tXJNm$j3)D;@=4GFjCdN@_x7V})HT64d>;>=sw zI;99+KRlH3aRf0>3@>$KPWSN&N2z&+#*jP7Yvsz>AoA6>*tkqCp4&eMSl^Ru5N0Y( z$%jv-*APvBqjTuQ+2hlWHWGTOrx-jbj$t}cOO}UDM)D7rm!5q}Onf-eW}%A# ztfg3oW%A(4-776mpwD)4oFma9wAKrmt)4cOGrNhu#?hNHL@;~iNPNs7d0rH!#l?_g ziDCb0#5++cE98qkdGxcj0kQ9;wp{Kij&N6&hpDqY3^*co!|**H`^{TXznQaanoYo- zvu1}2K5(e5X{K;!$!kkPs2mgfxR@!%^u`i#`9ee6uE%l<{mpXfb4!K`LJ<@s$Yz^nma`G$Zi12w>Z&KP9L{_ZS&r^QJ&%a!Ii$>da%q3z3~&*pwnB0>wq=X_kn1@}|NU|y?kA7^h zvQX*6>B>5!OlRbLurA=AC=0=mt})vE6xKPLJ6D}dIJf=@%eN*wrl4-#8~=*uGS@n8 z_hdqH#9MjFNXfkX+hwaaTO%_WYm^9e)Qsk9bd-yQqv!?i>zuaqFsnFZFg<<|UhK1T zb8c7P+K;mJx+aLbwccAl&XZOceXw77)t`Pf6dM-(se@6gzRXVV7ScUPStWs(GXKtr z{qj~heWLqGx&hEBWC!iefRG8;Z2&f>n14r;KkV5b#sPTN;${R134_oJK$qu5M^+>` zGbf9ps$^sZRV6Zh%W&EQPX*nhZ3qcMvigzWeD6{ww*OnOx5g`)ob%>r=Er&Aq#5TTVB;tqE?CWSI`GeKc@(`^~YjG zgg>&l8mPKYIIOzm_d%SM${R_2D~|tuBFB@H>aFcrHYxZq-SVsD^?XEMp@D+tz_$#> zdszBW&*OdTH`2-y!E?toz9i1K@ZCEvl{HA%h4gan9(tJ}y$=>3Jp!?c1c+5S7RJuM zC!>w^N$f01ennl9f1cX;|2n;OnSRt>-=E(e(SKQg){p()x;gt$sE!vsZi1vp$Rf|L&DmdK{G)d%Xh5*lul-ro(u~qB9+kupkSRC5jvLD0oP``O zGaF=qR&_GQSQZ;ja_8gIo*u4>N9D|W_dfi5374>{`&R(=gP%GHq`v|^`|9JurLP8! zJUJpHxH%$tEVj=rJgC}`Vvc`Yo3A6MSdqQ>eDI+>cPs7_?&dr1KH(E{ zHhp9kxOP7$KlB6ASSD{fdZS04_cuBTAA)8@Xm7dl2unQ9k}9?02DvXGLGX&l6$O|FPX|}K7kiZP7oT>;$P9e zd+HqXU4D&gQ*^_&%Rh2Pjx4UYaOVBq%q*GX(7WBP>C85y#%D~?0yIu%(GBuo-@LnHA2^4mO_hlxxCeAsh)l3mIqk= z#J>p@5MyCw23B)_8OyH_{NFd;ioym^y!fzvfl#4y(&$lS!Q}-qUPpT8f5y_|lgD}T z(^CLXsM5-XEA}vXsG48WyIk=qSXL6eh9)U?FJE*aHxIA{BAW=AOb}=KUZQl1@$?LbNoy!msmBAii>mxL5AU-jp z?fs9_~!4Az*9h$E``_E7ujK3P3Ro|4uPnkRH^Z zJqmkc09e}D0m1Vh6O`Ng7C!7~Bbw+SX;M}HUFhF&h4cIp7-(s0TH?v()1&D8A*Mgf}wDyjpH4sh-S zS|KwtkVg3L${4bP0Ks^=z@qN2?LmOc`(L}N{~xA=e)qwx`})P;3*`QH|9H<%eh(Ok zvI^NlMMGASp<(D@grNzQ7MB>58h9lOjL?Q4m1U=V%o64Tv3$G*&(Y3(pgseJ&xs~JnWD{O} zk7!`hbY%u>Uf~-^j)~6HRLAmSVfzh|GRm`<>wL%-88&2#%*Hs+W7MCRoYkwk>x(ca zQdsIRU10e6$MXk|J6?Sy71^2Q=$hURTi`F&UOANadUPHO>h9Zoh@YGFW~8&sj0HUq z>qx+_^<{kAJ8XcX_zvFE^bCaebS+Ev)^eLY0*bYA5Eb%z3-VvsF zNPVw7ybWFz=QUnU@E7pnTUG{9=H;yy6mK1oBF|74`vwrzo}KaVl}sR^3PZbHb1L9^ z5FK}nDitD5l}!4p8&9_S6X1oOB$muxKX@CHO>S^$Zla5qd6v{-yY(Tp9Wh3?A~B1= z%Gh%I#eK4*7azC}JlH9*)C@0}RCLG|!BR?ih%0a7N46vpzjX-DBz9bycY-vEn7`SE zjH<NFW{O^W zHo`kQ17#$xl}tI!<(k!OAtTY4@aY-!SijW>BHFN1Y(aL0QEAW|)$uK4IhR$2j0;SI z@nZZQa=zoY2cjZ~>(4H_KG+Ow2Q+JdRfXR>`G5TYvP%0WP~P(U&q`{RGr%(KH)Wyv zDDm$K#+I}49)-O)0uNiq^YiH<338R64iXrG6HgWlZM@ZuP^XFBdHC7xe>`(t*#8{O z{?!A%)=^joWQ{t{#;Q!L_Kv;MAF3}Qjamj{vChML+$=W)A>k4=fOlMddGPbr$4h$p z?~;_bqnHi(?NN)IW8ZW;IXKCA%Shh zFFJDXfwVsh%IM;luEqPl=T&+8vRbOeZ}z{R3U5%9zK2&T?@+50zr63C#-7aRP*iUp z9PknJ?TrQION<|q=7&??YbHDL`VnWSMBW90x}so&2^uLd?iuUN6kF?Y3b$oI$zo!} z4^GvGe^MWO-(4{mp1OC$OcOF_PoR7LJ}bv`Fxa56p>?+kzQ2i|R`YLyBSTop4XqZLevx08ID3p^l=bS>l{FS~1qx#F( zXd*w}z)?XBvPuWJOr>09;dTZr|NOkcP6(;gMnKJ&c zxlwgk>>nu&Ov8uJ5AZTxxFA35I!0Y-WhZrg$wIF;9JtA#~eQYF_^Gbw;h>^(&q)iJq7pf9$XEN=ULs5UJH}o_6yGTRF^fMmbwG^}{U82&iJf=jlgcro2@62Dk6gl_K zaM$;pHo3Q;*O|bzBJB~0NtJTnJ?)h6wZ-<&_&5s@1CRSE9Hqc*z#okI^$L`i!Ia#u0768_t zI}dysLoUZ+zonl`JM!4SIlNb&t24R~gYQfhS@G%=hCVCItZHR-=ga)GWfNl42qs%> zjsW*t0py(KfG(=q{tpIp*c;Q>zJw1M%m~-tn<7fY&B04)aS2(wzYm^wtN2)E|AgBU z!7rYlnQ11!bKEH3#xrqLcPt;e=3c9kdBzb90?`H*7c(0EXVpT6L}KfaruKBl$q)_1 z`gnnRiqW~R>{|LbDcs}bG>@u?>YM{KS$oyf?Y?q_kXi2R?{nG9EW57>oG?8{GVT>~ zocgj`+;`DMp7sE@DL=X`PffqZ{-^YEj}AMLHE*a~N*Ku!hXccA#SS8x7)AuSH*P}9 zn=jXc(>$Dmw}@>@8T3>L4$2139e20bK|lirQf{;T>Gy%{bO6QcXxZER|Hw+Vk46Mv zrvFtzj;0g*E+GjS?0kjuHsU)dgyB9%uNdZ#QkVYckaV*yRy1Ux*bX>%tdk*9Lf(&H z1J8#%kcRxrWPGruB$?j8(y}EXkL5f3}jN0#WsF8Hkj?Xg?eKAF>?4u~wFlEvUa~Sjcl2 zZyj*e={|yaTGyu86Sq!yX@VCdWv1rSLNuCG+~l{FSIx&;9V?wW%$0u<&woD#~ZkaZFa6M-mZrO zWv0nq;l?UP8(b|j!auw#285W?KnL4J3$V_n;mBnV9VEIL=9nnTK^;E*Ddi0E-SrXp zW*^HW7c7E;yduuG{KLOZ%&u;z?tiRST`Yd#HIc5tlAo0dE3@0K{r+2F#B;059Vh>pR{Q(L9V_8iomY(dsfV*4eY2?a99Op1zf0#6xUW z$JwYIC@k@yS*5)NZeQ;>MOK!*aQcwf z37Svnv)f0$i3u^<#Lg`;E|}JhPYT%55TR@2mtv%=dl>Uf2#+vV8@C%i^ir79xbQTw z@}9Cv)M2q4{%qEC z^)HAqD2eVSD3=LcUXNSFkAD%2y@|B@VOaw|Gi$ zbG4%@V02%AV-B1rxsR7=?`kmOd{sP;-(D(mB+`o(xU@HE$%A1#z9KwYL zbf}?RnsiqwqqX=}wdFrZlD52KXD%h7?Tksv61YrWhWF2V$EcS-k8F6&-$_G9XTU zc(~cjrny8dN*CYTf4;DKtDA}Kqg)XSSmJk}6xX@48h~L3po{#c6t}W8GuHbn82@?} z?AK3>fwwMx?UUaWeO{ptvd~cfjkZwJh{AaZ;b|lu^&)47J;uX)QY=R8@K{XmT#Rd} z(MoD+VfrE1aM$VN`Tea>76MWNd@7&%(3VyOj8M22*>K0X?0k8+&oI29DflRD70`9M z_^YL1->3cfzN%74b{~w6Y(rg~-TmY#=LZ;_!Tl8zXUD1b_jIPUEDP}1KSW-RuG2l7 z=E-atxG;qAwh8}fo=!}hrs2Ul44O&O=AWQ`Y2P$0ps}E8-7iq|7_SS8=i)_1IIC{*q2 z%VFOaOcvsJ6tJ87B$=LPgY32TaG+VxmWOSt&{X=wGxeco;>0$`1D$$RFs(U6TV){nM?T38My?11;+_~2Oe~WnQZ7oMxOcO4rBI7c_ zj`b5r`(hh4(-`VdXW(Z7$!crMJobic4d$>EDmN7jGTjRg;g~7xkFS33%H$Ad${gE| z_Xn=qa&q1O898F}Mczx?!yJQ0>o>Rv z;#eW1&>=(a^`?U21K}{IG7f-GRbDl{v?-*4+bxaCUb*zl*)%X5M=y{|WDuZ=K-?cg zBTZL#;Y2(1p?|OX{+9^(3JckS_4~FMzk~UA{QpJB|0@^$J(`TH=$!3rtf?s`>8E5Q zX_e|#6{yDP=_Ki;Xz8XE|38!+OPAbN&fj^a!T|t?{=2FEcdmxc-qFIz#^5inmEAT+ zVqTda=z^a0-iF-ii+w+B{TWBZ*(moca6?j;Fam^g)Xu5~t;JLQ5_9^Guj&Z9XvJ0> z$3*|2A$e+~Xro3o`v#?*hqCLlOuc4qM4^eF3`W)E1C_Ms%=bX4>PB;v7E9lW^4sDH zXVDqH42t^JQd*c<*c`lkT;l7kTq$=FKY3CJg~-fSBc6zc*-YZ?M4i_P)IzQqXq~!Q zw{CbVV1C?EVB1DY`c0z+)hx5_bxI0FCfVMn!_U~)T*9m0mLJvLndXAeuC}Y}%@3-8 z@8AHR$6&4-rSoKNy<0cxHHo$8JgsucIEY$mVisJz98MWXrhWN*_}$u|2A!>;iOJxU5yh z(V$(5f1J4kO-@8#y0SZUH`r&Twf5rjFzUyUJ|?L&Y|NMIF&Rcc`;e-85ULLtxFqQW zJSo*;1YZP~H+ZrnjZaD_fQ&(S0%cGv7Fi2hG2$Yhc)P=6VEkW6?jS}}>1i67d&3Ed z(iw3A>61z{a)tHKHBA-7+Q4KYAKsRu@wjwKN zzoFUy0njPJ`04^_zY5VPB?_a@Vs_S;A05ATUG<@h(?V||VOs0p?MIx}7n-_l4J7vB()ZMh|k-d7gW zj`prDs0R*la0wp+ESQd5uxR}M^_wv-uuK%vbyX@#81RD+zr9(U(KqvaD?KH{(2T?L zyC>TJ?F30oI>WR}&(Yc=D@c=GaKykfYbKdJF7^AznPQ&iSaw*n7P`x>&t8&9VqEIp z?9utNY>~rJzbs#z_3%%f(JD!5d8*o?n-U+P|BKeg`@V1fVax`$OMSVqx%nE=>jB`i zT2yYTlXp%em(9-%f5y^x)1)OmN(-evsvEx1ZFx4PEU6_nE$DF?ax68!?y4GnM7TI) z&B~lRref^ABm~P4EGoOVn-zc59L1<2{*PihuDT?n5`y^$GNs!_oz7Aq?XtwKY4cLB zGn_y9OHdE4IitR1{ot4EbXV&%)cyo%xUhPZ#j+B&e zY7D*D^G!sL%)GDcC6hW20_q&L#9err2k|>@!gmqeMZGlFb#km{-qAO?_srBriNwYu zlKBWO*GvFqF#Y4Lu%9=fY(qn1wC5e8z&cq?IWmD3bhC9j8mW)OSdGCzp;ZtfFPnRaBQp`r>vt5Z4dj(9@z&G`>a~^p;UsO!*@=r#ke;)? z!79&GlBVW#(+C2)LZ8#>YR-B}W7rF6M|-1*I<#rM@kO+%H05Qs<070-#3uFRy?FC{~q^K*BqSk+A%`qu%yU6O6 zJ_ztOGD9&kjFmU*@q8Bxe`Hz5$W77j53WGHq6`g zWswC-xSI*J6 z4pdY9^BUl)LX+0v_wb6G0(}oa^+Pp*nhJ@Oa7!X7azAo)?hFrPNUy8m$+a|*!H zl(3@!rK=JIH&hv9LoWfIY=V%EhYb1)PKPoS!j$rJF6SLSQmQN_g$Wk!zbWLRGWGk? z4!W!5Tcu4pYZ;V#ad|ALVcXb+sM6dreLwgQETBvr9OMxC$%`cL=sk5 zc-Z#j8V?uabb90K=hQ7h|L{bHV;^|X8yvYSXbv{UyR|2$?V-5(>i-Y3aswO9;rJzC3~)MSFAV)s)l&4q|0-LFKo$-uhgeTnp5 z>}}vHzeAPsfEvnGz)x3_@*Da@em(A$=6we{{Gu177}84$IySsJrhh=^z-&BKu^$FyQL&J7)-bS=vd-c|C+0})`7|wEJ7icSQeZ&> zzR>ODA*Y#|HI<~#T)e9@75G*bW_4lud*wu#tD2-dLtk1b`yL9mGSOvKS8c30#28s) z2sQ?|?{>FTNpVQ9JP*-GpWge*PIz$9&5N^6iMt~@Cv9d1mab80 zT1FO8(*!016;8S>8q@_+C5&q!Pkkjsbb{uaKtdF=TP@UX0uWh;c4mq*2UO|Oq-$ZR z!`>T8C(X_X7lyyz^Mx2pjveve{t z*~Aui*dr?g9)hc7h}MyBLwuRnK3>^{z@NFYO;X|=3xv+Bpb7(2SD7^iMeBW86w>x6 zeUzX~RX{dSxtWni1y*rAZr%@Cjsapy87AaIOqoCZ+T;vj)}h=aOf@Ztb{8jP5boH- z`$RjCw22bG`4J`%WLDMn%s;ENjsdaH2fRV062`+mUBh0ZjfSx~jSkpjIG7}R?tGng z<<^_8o7LwwjonrcsjpeKI|L=(ewZ78%;#jT@oTR>Wc+<4$#pH2hEDB!RN>DSO6tQG zGF3A}p<-&*{n5_}$u7%qQLcW0FaE*JxIwnyCkP~HJ?W$K0wi2Huq%jH7@fHbrFd3d zoTb{^B+79u(}szib~exGO=hAY$&uPpiWE6JZ@Ek>3{3zRdVGp8FTJ z8L13o+XnAJN=>mk!c6aOu<|raRE@4O0kZzp$EDFfEN^TSyN+{F^tUSWV2xpIyG^XKhZ!}c~6qHW|$5PmXnxRh{?Rd1Ts zOr$#l=QiPzpTnw4f4+&-KCdB$VW%ckCJiD`PnS>Xf3#Nq^Oa5Qk%FGv#T~8<^huPlj+tO_ZwY~PNpE<2d#eZbvEj1sh}s`)0(4zvrg76B7>dZOZ`$EXuqFOv&d#*GlNq?k|ok%A?xkB}7tx7Dd&; zV7Q%JKisV|nnbK(2P)7~Q^NIw{8u|Eu`tI;p*~}!%oG(&(V{2B+P$>Q1jZ3>d*OiQ z$&^)AKRz5p#2mAtq^wnRGU1A$0k-l86A1OI0aH*yjJ%BA6R=Y1UrBbU)TJwC`t(i3 zPnlKseQY{P1WHA)qHzos>`n8A^%|h`;i2hRaR0G**|6O+MGKKx(-0_`{!qE5(eD5+ zo~Rx9{k>x$rz8U?7n;~Vz)!oy{2-NI7{Htu*Fuxl0nubrvwhbmdK(qyE27dfbfH!z zjO~2(t)BUYKu^BwxJ+pZ}i!$i#P4L}*eQMyIK(WdK~ z^F`xykLBtBxgxGQD~Hjk(>!2}W2hta;`!pex7^A>14kU%OT~k!Qx8AVMLyH3uH-7O zAcMQbcMi8tfwKeUIT7n&>*}{GvchoP&|#{FZwk2c`|?4-o?~{YHA1Ow`};4`s%NJ& z;IG)qmV0(dyLG<`NZGx22^?AxN0o@C0>CABnPjaq~8O*zZi1m`fj=@SSp642Y z?*gFAAr>{5eYyGNv}3NplUr7L!-d4!Oc#${Ln8;hM-JOH)e#7N3nQsyj}VCCMI%pI zIv^!s-(g3zsK_9XCkmyEbWR@`1rcm(tf+@^m6G2t2Vww!2OLec{8=$lQBa=fnW_^$ z2crOb&bZ13>l`_Wn^Bq|;R^P9c4NQ8kW5R^Fhkd-Z|5bU($|dG_O}UFPY5~oVb2CL ztXx>?KlW>89#BRGVW;nboMO$`1HOCR_Sh2pVZ8<LSz9v@M*nD2M;NX5I1WJ)s*c63NVqPl2@yfdKk{|K z#O6@p1GM=m015I{|FCd(zM6`J>v7=o@^DD&;Pr6-{x)dK!|Txoet6l*`uXZRUdc)m zC#O3eHg+rGBV7`AZ3u^vAT-$MAb14J5H0?^h8f}5{jjHVj*PKTj{X*uPP6DsOQ1>e zP(oc!iPLt2*_o8DJj3dS3L97!^~-8Ld_;>QK#+ES4^1{B$SkQR>$0HK-)#!rc5u1T zNJR=U5n4xhEo>eIf0-PeEZ++q#IQ*JG>Nt0Kyzo~lW%V5X?G^T;K1A7A^;;621PAD zt2Z2u8hjF(Xv`J)_VVHI0Le6TtVdoVp{|_0GSQ*dN#Ae7v2`hu;HJw|-f1!wSoN=u z2`xD5Ptw>wEX2>SF4i&G*(1ms0i+Z~#cp8Z~;&2V>Q^GW!Qt<2 z7JMN9Hr19>S>|p-RjlTTOu5ylHb3>%&nWErvIGht5^jqpPrvQX;=rV=^gtnxJ3RhGCeP(j z{GIV|m>26#M-sWWJ&OU8PNpD>!TkrKum;vUnJsSd)GLk6`+hz#lparRl7n2?`m!?{ z*kUU1ODmVX`X&-+-6yYya$dS{v8@rInyNwyflpc4-$Xz|E)33#KTZ|xC;0Y3y$#7nD%arUbaV_*3?86oP4qwKh|K{B4xoufLVA?`S|I=N`{g zt&?OHXLs3XHm4}Zz%LZb<_b!ttux@;i?+^herd<@4nJnz1#29s@H}<4*`vBkb z@(U*oeUvm~{{ma|g~ zx91M@R^vkWb{jPd2B+JRcWk_bq4pn?2ANuPiMwKL%b{2{1>HEOouDvVJL8!q;U-*2 zRwUMDNDS?#Wa-To!^32v*zV5%SQxpxHK&y(O(A^zK;XNICT zwfz*t?Ma<_r}BJ%?8{kyP*dVZ=`SSXX#3L1it7Qb$IF=d^)sh4G@QcrcJA%o9HuU| zt;0HNGx}{^3NV`U(H_?mH-orSkw|BnNz$;VG@f*@!eR<$S)#Q!@N?}y;x-IayH?TE z5`4BLTHkFlsrE}f$1I>5S{4P&_zPXHBMoEI(8SenYxy8}0(}z=j5iSS0ou}Ct zOoWXIDV>gkgr|yS`745RpjnZe5GT*Yv7Pg1WuPeox(-Rf@_k+Ar~qb|lP2Ge4D-HE zE>FX*+sE|-5c2i#T(QJ#DBYk@t|D%YPwnD_yoEZfJ#r-Y0*Bkrk+el>?J0P=J6Vy) zwTT`(Owp1h_5qVIk;-_mGP`WyTVUke!&@qeKZ^n({5{gFw+_cw&997&!?4EK4f8Q* z;;ro?joWFE#b|e+qv32CLV;WQh%>0Fo|q?5^eyq{YxqYF3=uwGJiGYV`wbS(8JLYc zt4Tf+l-atb9x9XNinp|+VU3{xLp!4MxCeoLVcH>MwIF36^;aB$DJfV_%eBWzz!^B44E7yGmH&8l7yKcpK z*^{upEx{7z2N;&)c^n!jyO8P}( z`%x-)KH;oWf$9=QTKi!L>Jw;nPZA*a_|%0Us%&vESocG*ZV64K5v!iT_;#^+36M2IC3mgbTwt3>WG2%YIIxirPv#%;q-(HpS(7rBl30z>3J zmBX2aA7CGMfBuUA6J=PdhzA(}!1Wh9hWpouIAVrUdw$r_IlOWMT}#(cKq*S|Wx5_!XlNfHa`8QQvS{eXnI_P{8{V=TE|qV}3|edZ7A}#sQ$(|u_a;Zk=71(I9YniJ z!4-3BB+t=N`ViksKj?OC{~4wXM_rzfdZW@u?vTl)tvs$}5zQ*`b0W|uwdYGVzUVK$ za>w=3JLYxhCeo%&V*HbO3fQ{K(R{uE4S zNHuqp((0o!YJcL%+L7bLFu*}E794TVn+xvCW}97PmV!sg(G<5w5=a-hYo4+=17d)0%82I<%5@=iVjE}e7;Dk$kzzOl@gVY_JzV~q z8HsrPcz;YgtDEhPTAQ2AzGx<#Bka&s6hkx-Ng1$yLc2#xN9y(QRh(y4z`uiSvdJ{| z9k+yl^|Z@TPeb3mxKf{+({oQ#H=CQQt>V^Y0?Ko9|yrTEZ9oF~xkwkULg0TQ4T| zYvObS=GRy#a&EFU&8W=Um9f~EBhaoh&>qeO;%uR%Rcj`SxE7C$PL7@(H*CAd6h8cO z6RDb-XahGskCP#_v+F60->B_Bv^nQSKobymD9}osxmGR-!scs#L?4i+r1mB`$njD} zKWD{J@7yN?MK56pPm0AZUXq_b?maYsOM8ftp59o5qINK#B&B~wjE*-II~x#qa1jZ{ zo}KdRIgbf2glzP~4r3ufMhT`UxIGeui8NrZ0gpnYQnT6YXX>6xy28&f)!=JF)%~`c^L3_DkCVg&s?aICD=ylfPFTt zq-LsTce951Xiq7K=!Gl?_G`-O^nVO5)&%^hmKnm7lWq0QJxrE(f#8Ux@dt*7IW{KO zNhcN`s0+0mTPBUIg%GH4B8_Y+;J|ud*Zk~~a$}9Os=N#ZZYVrMorMUA>IAgF77nvX z-Lo%{v&vX)j#8E$5{&nk0$2>{;67Tt*?>p)g<_&?nbZ?xh~m&tPAB7uC#tY0Vwi=M z9ZtJuSy#7=VD29F!liebm4c~Ok_#f5a+_K0DF`tX*yW<1tDDp9?Y^U%)%%n4C$G=< zgqOPyXa&0eU*x9^g4udd3bt)4I$x0hye$rzL~i!S0gibyF``pVy7Ym$z>%ekMO)Eo z{pG2t1@4>)SZ~R9rW_A_B=V&Pn`#04YDq*>JD|?^L3I9#C^f7(nhf>|n%0#{=yBw` zoNDv}?lTRF_eiTt}o|CJU_vP?#I{k8fR(h?N$ErH2 z#si;uq**Jt3y4N@9V>(!9-dqvOTnf!9`yMe8%1*uTwRWu&T2*fkW;an*RId2oN2{E zZuk9?m_GmzhnM4>PveN{3C|t4ExT|HY7z?~u059L(rFNzEyzJZ_Sji#HDBgC5`#ul zaY~sI^yfvp&`VI3=JwQt%YrhZP0hv>*4uQo*3l6n=5O5)M`Y*j%o&EjEGKN&C&~uS zTh&p|WMB@0M*LXTAkcx%CnCmpHBGK5cBY(jp)gK|3yliIyb(Ims%KaQBFO8^(F?c! za2c%pc1gP=+q3-ww$^%rwC7V@Cpm@hLPL)2_?`&oM)#GzI<#};xpZ-iP>E{f!8p#8Y|e6 zw@CWS7}4y35E^JE^nuc3;_Xk=_P@yj`JfFmksod8@^`{(jPY&zwNoxIAX8bqQ~J0+aC3ge;MBeZcXpTKpnt{Rs2Fh_nvEq;uv>Uu9^ve*)su!A=wxY zLpF^B!?YhY7-)v<8xb2uw~q2f1N9{d4O% zo@*kxXTVbL7WLrA1ZXMR2a|)NLPRtz0qIq8b(LU_4f>=L8ET-Ic}68 zMaM!M34YW5^PB3k;yTZCH@fGY$Bo!@H}v!>opD%M1ngfOxK^BC{R;BgO5W8IBb5YS z=J-Os_#g)W)4&VMYITOkJlJ|sjk(t6_XA6%lnlYOSlL+u_q?INxNg0tF zImm!vXoPE@Xi^5l7D-Uc$(9D=K2{LBSKB}}r3`p>Ep^4VhZ>?T0lt4I580mY*Nzbn z>kx2cH0o5gAq{F-b+kaUp-NT1T-&}OeFdPM4%1Dvv37VW!;$K~MMgo6qqwG$gtBv( zqI?w2;P|X-f6co#!yao_|KE&!SS?oQktf(dorwYJ0$)6T8x$Q=F7oO6vG=Io7o3$N z^lvThu+}X)je#9E#u0i;F)+Pfnk0!Y&W#XoCT*#pOgWP!r%XvA=`9$BY%Km0^did; z(47RSZU&_cXx^n#JKq*fbXR+*4JD)*qoa_?CN#qop4kg<@k)$0Sl4lCcbGdTY{~lY zm#}s6>_Zmr5R!Q)ww&#`TyDqSsAeF|{AKo%$X!3fpSya0_%DoA zKA;GgH`o?NzdcW%OCvGX=_XklGJw-SFy9GxfErRAammh*@n0B=dM|wVMy~NX5IBf>$wplMHlS)j_+oB_+5AibSL@XsfeJ@jjIxyrBi2L3 z@%%Nl*8*D!FuF+JRf64&qa3& zadC8bJ@1B|Yb5U;VhRpeRq{15)*(;ne_UC`PH|@6_%CXgQW?0?O5ykOaeyC?Efcy6 zqCr~AVUwmAVeg%^O3$?kepWIf?GGN#7d_)GY7mgdYPWb!Vsz%&o{sp{rEL zZE{ZAz+4@6=-N~etwePrw{#d#+(yjgeh#;aeWpiOQh9D zTGNGdjS;2;UjSF7$Lp5oP|k=v zePJvq60A+Nq8#YrQ%A^_*?sdmj!0RiM6V0;kHDW5ttzD9RKQxt7r@zfum0;%=>d2lIZMtLpAdE3ICS#kJyju!HNI1A_L zV#>ri>_7ReRUvAbY)-HyESaJg3=5D#sFlNWb{25_e7*8V5W+lD7ADqRs?x%%+60dH z`SpyVV?9x`t^BlgewFH4iHiD2O>l5s((+vJn_hBtbR0I|S)w03g#s_g*`Y8M*_FDj z#F@V7`=`TU#jV? zzqm$Ml5r9jM>%RXfl2JU&$gH04TdV>lPwzGKopkIz_N%L}yo z&lsaQ@iu2SU;-GZckl%H?qT0(}+Hr^w{S)R@^Hqf$2m_WbSNt(R?CHHc)d`J%5FAAr&d+r&V>%Vd0*K*3k#7J}vG<}C_onir4 zcUCWj?#e-yf@Z63R>P!cn_te|=3}na`B#_$5&=QOSJ)Lj0!QdpjAQhlsJ8KG``Bg1 zIfBdV17&h!4LTTrZo zw5{qATVco?i2=3F1zh?v5_k`|bnwj%DAr#cXu%v9syc<=iZ#dg3YpVzA|*mz+o7`X zw2pwaRjSTbzT>;7~E5 zW^u*1(b9L$e(fCj#5|rB9cPOjV~Z_)MO*5qR>}QkzEj=n%v0=^?U^s+fk8+iz7fyA ze?VJ5F~qKV&>N2Xc*mJL%>0fil>BRJI_QrXd05*+^L|>Dtyj03RGk{{qNFcJvYN*d zsET_DiI8d5_tfS!0Rr8Yeoqk-w~Yp34|dk!d^g62@&8B;F$aNNDz;Dmm9dBDB=3Us zA^#O`UXN+P_j*@MD4LaDA^=VcIz4Ae0bPfVF88?L`~EP&`77oHrh&Zbj+5Fw@TPFC z%Q&k5FSnyscQeC1Y{*e0CkGv%zfHmKx#xZnH`MgrvA^X`-D zk;u5J&dqYVu7951FSl45yzKkDxBiqEiL811Qb6VX8OhUO71>A2G=9t67`!+m^3Sj{ z>PMtu+l~3*xa&fkS~`V;k-h*CEyxErkUFpB!x4Nyv68OQ2v2o(}zE#XoY6}2Jg!Jf8_ zY3ZZ*Ew~GJS6v<4%5W{=Pd3Rp896T9d?N%28~1;k@iN zm3;eK__BY00d#TX-T?hp0x0oC8DjO323P_$LF$OzkpbW9MQOX!tRj}PMk#X?q%M(| z3Z_CIgrxS^5xH3YPMzI)QjZpWCp!2|6!#VXJRM;YZ^BOtKbT~c*c(5H6~GmCsR5S@ z)$`%PK__|jc2WEp_n9FtnooQM{-QiZs<~&vSmU#o#;iQeJQIU;Q>UJMZ5d%sRQ<`B zewKC(=5t$gRZI+72yi4#t0{4TY;F?XoXr~iw;aveQSic?yHS+a0Z{|f8rLmobpas6L7JMHohpAPorZ%K5J%ue5&o3-|oR9t>FVYTs#LXQO z`dg76p%Xy3W9Nk=Um&VeAV+$e?J|%J@73(l&n#9vnPj-9QO=XJw$*uiv)=3fwI+1x zr(*vHTj)PD_|*U7rK2t(Dk=l}Yl8egp8h)^Voh#(gug_Et7v&p#$;kT?w_7lZF>TR zu$lM=`aM_E5TT<)Sl84Po98GYe|Pq~HASFgGfpcd<`AtHpqfUn=4=Siz(j3N|4Tx- zp7>M%{MXSR^}Dj!{>P8^YoPgU{QcYHMn+OtR8CpcL|NKyivgzhN*#f-CMXMT%Z7bK z5z8RfW_-324_Dikg(H=a^6KGMeA9ykV?G}Ne=n%m=_;_H2YgFt9s9Rc=RuDn*7;h7 z)~hbNf`_@y+J@UtPQzS(7o6o5_zw7WB@oA7*&<$?Pcd#7i*y6It^v%tJkxoMvMc?a zi^-!W{hk5^kkT9lTh))c`vIfTJ(lhIIYM)1E6?fl?^wEo1_@}!tfIxY>P0+Y%Ix!n z?b+`I`+k^A@nGmCLHN~#oP8NyS<^~U(v`eP=at$e{9IFe$fvXpazCCr@ zS+N8fE&` z;%meucwSgh#MqdAN1_VBlVwNbR_-q`nDD@T!4IBN&n^u;uoNzd0?-(?+Pr1|dIxXK z%I1Kx;Mza*#}Iqq+ufC27`A;1*)N=q^`I#lRo@3w05k<^8}l3~f3NVMy=I8r_iP7H4>glbLIht(2Fe+=D2?GU5>uRw zhA_kO-U1D$l0qucc8WbjJ_u&-Rf%&~NUNHSC>VbrR7TMw(#z*nvh6z}^e5Q=X-4Z{ z7E*|rByqWGLPH_qkM*@DYf7;l($J#v5j$5*T3toah=BZ=2n1_X+8{Gzk-HujL%5b6 z2^J~}?TXQd>}d;W2O3nm18IP=B#TNrf@adWfLn_sViAHbUh9{yD@KS44d5QH9T27;xa!=6<@5KRB5a%s$dp2AL64s!rf9L^kO%l@1R+|)K3a$pM$}=;MIe4y^X^sK*I)d> zgX_w?%=y4pNQ z*0na)%z$G<4)BkwYN6Qd$VsLFPl=It!B&nL#f*%wWWIbd$H%ncrLi1HKnTLFo5Cz> z>*xh=l=Yhx`0#cq1Oc(v)EYcTJfNU0p75G}N(>=06mgl*00LNvdU>3mi0T);J*$>49Ek zexAWS&Mj8IHD~Wm>fKTN{wu+!3^oN&y3$)Z42SMBp1DDWx{>nJ>M0ecx9N1y;9vR2 zrkgSe%` z!jG!&dJ2{{1z08J<7Qm#rQ>)-3aLZzW8ZOYQ z&ngZ^G?+ZHjfUd3nN3$qP{vPB+lmYn9J8Cg8R+sPE@(qiQ=<>qza4;rSjH>aXY|+M ztr}m?u=t0gWJNU}L*nyhFK%eETCzkas!nTF)_~FzlB%MGFp)@gH60U4?8YAEuBZTB z&X6j1Ts=Ilt$zBN=h7FQDa)?gaBbZ%d`N~;LQI}0@*-AKm>4i+MI zvil{H2Na@xh(HFK4zJh!m=&M0B=NGvc5Nv^hIvspQKs~u93~JWFmvBv2QvnB%j+SS z%&9j*GyAI^7QyaF-IX;wEkVCOocUVJZXBadSg1eZvx_@7>v0DnkVXX$`OE%7z{hHh=d%+kfmLlZjYrJSpXvtk`Z{vj zoJeB}I$t7V>F??nqlfWVZDEeeSg#YaaF{EenuXsCh`+vfS#4P)_g1h#ZdGvSw6xRS z?wxQdq0aKjt%)!Iq_*#FQO&QKOP%3Bfn$jpDJwEU#1ue$8#wWXT3ON-k&jpn;Oa$!@Cv#`~nggp;*F~v2e+l7C{ zj8H%h(7%I^?dN>i2y}b}%bIr+a9-=8^UtrtF_o^YA3qdF76Z^I*1b3hC7f9vdqa`} z8#i`#^bxFqPYTYji!d;ANnE$L9Z~&hWv;qLYOARsz9RW4x6!ToNH*A^rfBDwhrcg4 zUp-&t_)|CpQ$z+FAPOgXST*l=HEv|$Gkg{&Wz#WpMUa||m$lXGSa!QYK-=Qut}_ne zTiUdeW0gP5X9fk7vMI8wpl}=KJX#;zc&?*k(|W2jxwN$Io*fD#K{q;lf% z@b4RTLKBNW{*zcUTvt&qR2SEA64A{H1exyYJu^wTu20oVj?v7>M_vR3mzZQVY!*BP zpZ|FbdoFT_oUXVU+ws&EcUH4b(Hhxh_Zz2?cU&HI^C~mDhR7h48F>s{1(!jZv?UMkw&VjD<){nW{P?gSaaj4Hu}C0#{~+gJ)TG#gCG%7eYe3?Nfb2oEYiNd5c= z!u&~ev%eFutM1|1#1^^w_iCdav9<`{O|D96XT;jk{+@9Z2u}_Cl&o6n+25hkLt~AI z?Ep)&;bq9dLYTpQj`xF!{J}f1zQ<);{1eo{^e@OQ))T5?+n3d#9ahzG!w2E6)Wic? zE$!7L6ih}4ZU?pVL`yez2it55>@^v#2b#9Cj#F z_pm^kSn8c4kO>Ceg7J_vj?P-0x%wIsq=(O;4yo@9+Ieb6SumJF(G22Gj{6VO z>fCzjFUzUS4ZImE0lGL@Rw*AHbf`|ZegVP*fOANG*fC~jpGEugBBJ!ETxX4DWj62+ zgMHkfRkV%owSU|%SY=d-*wtMeu|qDGMG7be1?nchd(Ymm2K+-CDjqIf+s=V~xGAC_ z_J#cKSo=6yt45^Sabjian_^!vMdh{tg(YKz8>aK~9(E{uuBeIj2soY1#CCTallS4t z6{`{r6-9H5OraVeSaLUS4R4OImf4I=k45f5Wzo0}`xEq5jdgQF?%M5)3(2hZ%_|fk18}GO;MO^6bg-WN9*J5+Q9K|POpvLof73LbwgqpmN5sb{xCT%tW|b;>aOO0>8tKu?clsH>iVspOa)8Z+`DrSA~l_ zM5iiF8A>#WcOi0EdB8jBZi-ehXiZfKt#x;z6BJtzp^6%Gnr9E|IbIoI@@>xNy@DIL z@a~+imE$d!)Tb%oPO8>9R@&Cek>kub^`&1a`71wq6?uqtgn62=EjaTE4sb>yvVjYp zn1J+f7caIcC3E1SzRZ)e(`DqKwmVH0SHshYi7$R9F~3fr4Ne zV&p)SUTPEns>l<|BElv$UqgKJs^lhjQ<=IFUZAe&fxZw5X{WR@+CqkNCNYvjP(ysI zbNNVS#^z(2&aFt&Dq-5ZB6POPb@$L)T}J~{jG8N+z#`Gf-^*#@$d)g+4IWe{DL4xD zhYTPGvj2fP9U9-?Z6=L=>#2UPB@z4e>}iz4|68{QblA-?WILM^iy(JQA|wDo&rvN3 z(zgW6$AbowVTGn()73zLdCvqs8a?*ddY+Oyn_&fLu$oSF`RHlfc{DFe3Me}Y#xcOI zOoXdaQ<*iLDd5JFldz<+5oZ~8Cw@(YCpP-#!LLi0+{@6`JY*dWgZ9gHc-?M%O!YH% zvgc)wOVl^kVzZ!lK95k15o`cQerdR>HCorGgnBs922yA01TED&$ce=03Yr)-ePe(i zc4GQY7`^w2rSu{rN6Ae;KvtJJZ%4=QIW1G3m}-dE8SCO#PX0Od-wQV1sfu%vwSb|5 zQISSCHl!ybk=rzG6sl3u#YvO2P0=!7m=~7af{yKH2o^#3NR!S|pZp%jYlVeg+^n9L zt}8LYl+f%>xVci0Qrb8k$6jIWE~|wfXYFaNjilhiqqBVHDd`%wi7CYpZNXH->%nBU!3OwWt(|#X6GtD$(biV1g5|Zv zgG)tFQG_HwP^2PNK@`CYwZ)i(fI*T#5{TGZy3`_A5U9NMennWp8*9C=o}lRailVKx zDAxL7y+Ey0!CFz?-(<5{Ga^jryMBh1f982IJIC&XeZJXC^8%`~LxMgCO6?YX)8TPR z%@0+MnQLVa?;m_D{>MJ&$aAT#XC6%$S7-Uz5qWB2`5a}6vU8rX~ z2ZpUmwt1Qv8u@2vqf5Ztl{UwlCc>K?`Ni%@_O+6JTlQS}ytJ>bPW{j1OGOzAt?GtF zPkn>#d3xoy@2zm`EZl6@)uMK=>+;_lPj>73(eVrP{!o|Hgy5`G`zMqPa*a$r5Gq?6 zlQ;I_t~3|%mCySIWa((Ds0}71HgQ3*-%hr@edevZ7w8tvSEo zs$5oC>ah3vye!+go02>iHw>tpTyr$%{nIs@B1gnN-C4OyUY7h}qvR*eqJX4R8KW0f z*(|^GU_tNTZSFz2H&!fEpQHQQY9kN5HK8iFr)zOn>%q_Vp0$e>j{er>+uP4=--@}p&Brg``Jw8k4>MFr zwFly=XUy7g|M^bah>y#!075Fe>{6Sh~B4b3BP%_ zsxT^oR=)k?zq7vE*W3Nhc;~X-#UmDE{%44Co8pekr5#^hom<+csVMSjMOk)1WP*4Lf^k z(36z?smB}E9e;jx{Q)b9v|#oypYpVkPEVR`hS~iT`R;>;ysxc;?>}jp-F=EK>QHUV znxYo}Th8TMoBeJanG@?)zP#rt>(Za*X;(!lr>zf|DBWZyQ}mhGH6`8K+HZsBw3dOp zI)Bl9Opz*Y)2<)CtSbNfTs8zQdI~%J*>74{IH3v*2ThHE|FvEl#JtBqc2X;~rH8z=y&95=CI~Dn z#<5kwnWl7Lxz*Z?sU!xnIv+51-aMe-KuEGi7AIF?>5TXX@cQn$n-o64TKE9rCX%}? z&5-m#fwTI!GA6m0Nyd2b2TjF6!XM!U@CB5a(8Eill<7oLH2@f6Rg%_1@$t4$ zRi3s_2F2Y_Pw2jkTCaJWFFoG!rto-ddHQ{L~Jp$-6B$R3SSs}LU&fI><+Oe9J)fY7Lst7Qtn$F%LF z{u0c&Ag_ah@=w`=rtX>JL#nOYt#mog9$eaC6r7xm3i z9-3Uff)c`-f-_Ck+LE>q;M;|eD$b;{!q<6vx~x2^ZQ)Ns8an*}Lcc=iKwoUK2Th%T zL@f5>06=D8GDGTosh=CxGyvmy`tk(^VRq(dBXkY#9wlyu)L6oF(whZdAdKIYKgSwRc_;9AFW&O-lXC@9nnZ{}7iy+$_rg(h@p?;}D zrdmzM#hb(7@Gk)&U?v^LDoP+`51J~pGs6(9at5XcQig~~W?tncRFNV^(avz$c&T3? z>W-74m`>|*2VyHiV9x=8PCsjDv|??dzB%+0=&MK_yfIeYF1b|!>U@|t;VmiSK~pY{ z#14EBb5P)gC^#YsP#aO6Z?sBnI+dflp_e+hyCxwHH}h5h=qA(@(NIk1F}V||83>LQ z@Vo>JuALjD2Jj)XthC=O1+#3X)Psw^pr4p7Cm#KYognTD51Iw7cE(shxH#?K7uH8e ziXuRI<14qN%Lb6j^Wfk^Mxl`rqLRcyP$P-F?S)SqRPgC7U-|T5&cyOCT?hmoo`!5h zWg-MwBak2jJGVDy9=yCXJs#v2L5YIG9yH}Xh*%y5C){l@xwGlMA6EZx24Axd2vCD%MB=#w?N~M#adqFpr6qG3||v;k7vqXwJF_ ze|%zUK<-K{#Fy-b?cAX_3 zHH`{&Aeyx#P)uhpCpSVfK4>b3W?~jPw635(jbjn^#4FtJEyucygA3*VHiJ$9L;8cJ zn#^&+_wXfvI;8j6i$eEhQ0D0snIAND#hqAJ2-m^KkalalMG~v^)Ri_PZ}CO#LBrTB zwP4@`v;tx_vIkA=8$sws2>1hU9v=Y72GStOfVIC+V*!#Epr9Vf9yHbBK`iSH1bI)s z0Pg?M)rP5DE@o~nWNNqr*LR86;pFjVs2l53oDU{$LouDyQ+R}ad|{(Q$maugPydVp zYq=D%ht>M~aH%RTQK1w?t5ph8N1s^sdT%qhae)>Jg)@85)J8t3BiL^875Kp3PofgF zP?X5HA=P#lowKTHJKFfsKtb3+_MoY~u=!=|Z*4plz>X8&(;H?~X5Wc@PC`SIy&Z1b zf=j_4`$)rT`p<$9T6!56xSfO&Lbk;iC-MKcCLFYOjNa{-zw(UM}?4k~YA6Oh`@ z_Z1k}AV?S5fP7=4?6-n@zR(4-I^(mHzYnPez!eDLF^zdNG(Nhw-TpX;p1lM#^{bFn z*BmT8J|J;aJEuPy_7TXspjqH{+yIU^=M1EcA~XOuR4A&xL%?&~4o?2&?7Z+JwnNGR z$Hj3{Hz$5(G_iO`xZSuBoUP3nDexyX(oxbj?ga;9b6yfYFvANWCL34BS<9UIx&U+3 z+aWLGvN(>IlYKarSk??UF|LmjemQ;n4@vbq%KOE=;Ba2f%L7s`=AwFW3pnzXv(Rq> zVRM)TfW`H3vMQ%92qM-ugR_e3W^x zv6P&P%t^#9+J#i&syI%PQ=JH#W`v*pZ^9*UPdG=9^K=t-n#nwoQ1x(KoFd2RieNv0 zKo>!mI>wa4t>CCP&dNC0sUft|LGT;y1qZTmUff`Nna~St+;tSshWo+!U!0#wuw_H& zr-L*w+zU?T;=K67;}4-1Qcf2xj`OHE@sqPi#s5!qD%={*h~lhO0(O_IUH%3!3b%v9 zi8wp8z$zlM(;-w5ZUjdHaYh>9iIvDm2LM613mntKxwsAAUA5=JxEsMidvF09&cg{z zg*~)Z1x!#qczt;09#`L)q}SBPCh*}^;qMW1RgGQNdR4D~s~E2vf6^ Ar~m)} literal 0 HcmV?d00001 diff --git a/litellm-proxy-extras/dist/litellm_proxy_extras-0.4.30.tar.gz b/litellm-proxy-extras/dist/litellm_proxy_extras-0.4.30.tar.gz new file mode 100644 index 0000000000000000000000000000000000000000..484c28ba7b1ccc0b02ef5b00bed2e8550f7ce38e GIT binary patch literal 23752 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
O02j5a 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 W$^8G%&G)BwxF5tOk{@6QAN~h@a3?bW literal 0 HcmV?d00001 diff --git a/litellm-proxy-extras/litellm_proxy_extras/migrations/20260205091235_allow_team_guardrail_config/migration.sql b/litellm-proxy-extras/litellm_proxy_extras/migrations/20260205091235_allow_team_guardrail_config/migration.sql new file mode 100644 index 00000000000..000b96b3b87 --- /dev/null +++ b/litellm-proxy-extras/litellm_proxy_extras/migrations/20260205091235_allow_team_guardrail_config/migration.sql @@ -0,0 +1,6 @@ +-- AlterTable +ALTER TABLE "LiteLLM_DeletedTeamTable" ADD COLUMN "allow_team_guardrail_config" BOOLEAN NOT NULL DEFAULT false; + +-- AlterTable +ALTER TABLE "LiteLLM_TeamTable" ADD COLUMN "allow_team_guardrail_config" BOOLEAN NOT NULL DEFAULT false; + diff --git a/litellm-proxy-extras/pyproject.toml b/litellm-proxy-extras/pyproject.toml index fb6996b71db..d43b591686c 100644 --- a/litellm-proxy-extras/pyproject.toml +++ b/litellm-proxy-extras/pyproject.toml @@ -1,6 +1,6 @@ [tool.poetry] name = "litellm-proxy-extras" -version = "0.4.29" +version = "0.4.30" description = "Additional files for the LiteLLM Proxy. Reduces the size of the main litellm package." authors = ["BerriAI"] readme = "README.md" @@ -22,7 +22,7 @@ requires = ["poetry-core"] build-backend = "poetry.core.masonry.api" [tool.commitizen] -version = "0.4.29" +version = "0.4.30" version_files = [ "pyproject.toml:version", "../requirements.txt:litellm-proxy-extras==", diff --git a/pyproject.toml b/pyproject.toml index 9832ca483dc..80841912c54 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -61,7 +61,7 @@ boto3 = { version = "1.40.76", optional = true } redisvl = {version = "^0.4.1", optional = true, markers = "python_version >= '3.9' and python_version < '3.14'"} mcp = {version = ">=1.25.0,<2.0.0", optional = true, python = ">=3.10"} a2a-sdk = {version = "^0.3.22", optional = true, python = ">=3.10"} -litellm-proxy-extras = {version = "0.4.29", optional = true} +litellm-proxy-extras = {version = "0.4.30", optional = true} rich = {version = "13.7.1", optional = true} litellm-enterprise = {version = "0.1.27", optional = true} diskcache = {version = "^5.6.1", optional = true} diff --git a/requirements.txt b/requirements.txt index 69768b6c1f7..aca27bf284b 100644 --- a/requirements.txt +++ b/requirements.txt @@ -50,7 +50,7 @@ sentry_sdk==2.21.0 # for sentry error handling detect-secrets==1.5.0 # Enterprise - secret detection / masking in LLM requests cryptography==44.0.1 tzdata==2025.1 # IANA time zone database -litellm-proxy-extras==0.4.29 # for proxy extras - e.g. prisma migrations +litellm-proxy-extras==0.4.30 # for proxy extras - e.g. prisma migrations llm-sandbox==0.3.31 # for skill execution in sandbox ### LITELLM PACKAGE DEPENDENCIES python-dotenv==1.0.1 # for env diff --git a/schema.prisma b/schema.prisma index b118400b620..03b910db85e 100644 --- a/schema.prisma +++ b/schema.prisma @@ -129,6 +129,7 @@ model LiteLLM_TeamTable { team_member_permissions String[] @default([]) policies String[] @default([]) model_id Int? @unique // id for LiteLLM_ModelTable -> stores team-level model aliases + allow_team_guardrail_config Boolean @default(false) // if true, team admin can configure guardrails for this team litellm_organization_table LiteLLM_OrganizationTable? @relation(fields: [organization_id], references: [organization_id]) litellm_model_table LiteLLM_ModelTable? @relation(fields: [model_id], references: [id]) object_permission LiteLLM_ObjectPermissionTable? @relation(fields: [object_permission_id], references: [object_permission_id]) @@ -160,6 +161,7 @@ model LiteLLM_DeletedTeamTable { team_member_permissions String[] @default([]) policies String[] @default([]) model_id Int? // id for LiteLLM_ModelTable -> stores team-level model aliases + allow_team_guardrail_config Boolean @default(false) // Original timestamps from team creation/updates created_at DateTime? @map("created_at") From 64aeb18a10ef5ba962e5281faf0cb788ed7e6bdc Mon Sep 17 00:00:00 2001 From: Sameer Kankute Date: Thu, 5 Feb 2026 09:25:52 +0530 Subject: [PATCH 16/21] chore: update poetry.lock for litellm-proxy-extras 0.4.30 Co-authored-by: Cursor --- poetry.lock | 52 ++++++++++++++++++++++++++++++---------------------- 1 file changed, 30 insertions(+), 22 deletions(-) diff --git a/poetry.lock b/poetry.lock index 537367c5aa0..674725c2ce4 100644 --- a/poetry.lock +++ b/poetry.lock @@ -1,4 +1,4 @@ -# This file is automatically @generated by Poetry 2.2.0 and should not be changed by hand. +# This file is automatically @generated by Poetry 2.3.2 and should not be changed by hand. [[package]] name = "a2a-sdk" @@ -398,6 +398,7 @@ files = [ {file = "azure_core-1.36.0-py3-none-any.whl", hash = "sha256:fee9923a3a753e94a259563429f3644aaf05c486d45b1215d098115102d91d3b"}, {file = "azure_core-1.36.0.tar.gz", hash = "sha256:22e5605e6d0bf1d229726af56d9e92bc37b6e726b141a18be0b4d424131741b7"}, ] +markers = {main = "extra == \"proxy\" or extra == \"extra-proxy\""} [package.dependencies] requests = ">=2.21.0" @@ -418,6 +419,7 @@ files = [ {file = "azure_identity-1.25.1-py3-none-any.whl", hash = "sha256:e9edd720af03dff020223cd269fa3a61e8f345ea75443858273bcb44844ab651"}, {file = "azure_identity-1.25.1.tar.gz", hash = "sha256:87ca8328883de6036443e1c37b40e8dc8fb74898240f61071e09d2e369361456"}, ] +markers = {main = "extra == \"proxy\" or extra == \"extra-proxy\""} [package.dependencies] azure-core = ">=1.31.0" @@ -718,7 +720,7 @@ files = [ {file = "cffi-2.0.0-cp39-cp39-win_amd64.whl", hash = "sha256:b882b3df248017dba09d6b16defe9b5c407fe32fc7c65a9c69798e6175601be9"}, {file = "cffi-2.0.0.tar.gz", hash = "sha256:44d1b5909021139fe36001ae048dbdde8214afa20200eda0f64c068cac5d5529"}, ] -markers = {main = "platform_python_implementation != \"PyPy\" or extra == \"proxy\"", dev = "platform_python_implementation != \"PyPy\"", proxy-dev = "platform_python_implementation != \"PyPy\""} +markers = {main = "(platform_python_implementation != \"PyPy\" or extra == \"proxy\") and (python_version >= \"3.10\" or extra == \"proxy\" or extra == \"extra-proxy\") and (extra == \"proxy\" or extra == \"extra-proxy\" or extra == \"mlflow\")", dev = "platform_python_implementation != \"PyPy\"", proxy-dev = "platform_python_implementation != \"PyPy\""} [package.dependencies] pycparser = {version = "*", markers = "implementation_name != \"PyPy\""} @@ -1137,7 +1139,6 @@ description = "cryptography is a package which provides cryptographic recipes an optional = false python-versions = ">=3.7" groups = ["main", "dev", "proxy-dev"] -markers = "python_version == \"3.9\"" files = [ {file = "cryptography-43.0.3-cp37-abi3-macosx_10_9_universal2.whl", hash = "sha256:bf7a1932ac4176486eab36a19ed4c0492da5d97123f1406cf15e41b05e787d2e"}, {file = "cryptography-43.0.3-cp37-abi3-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:63efa177ff54aec6e1c0aefaa1a241232dcd37413835a9b674b6e3f0ae2bfd3e"}, @@ -1167,6 +1168,7 @@ files = [ {file = "cryptography-43.0.3-pp39-pypy39_pp73-win_amd64.whl", hash = "sha256:2ce6fae5bdad59577b44e4dfed356944fbf1d925269114c28be377692643b4ff"}, {file = "cryptography-43.0.3.tar.gz", hash = "sha256:315b9001266a492a6ff443b61238f956b214dbec9910a081ba5b6646a055a805"}, ] +markers = {main = "python_version == \"3.9\" and (extra == \"proxy\" or extra == \"extra-proxy\")", dev = "python_version == \"3.9\"", proxy-dev = "python_version == \"3.9\""} [package.dependencies] cffi = {version = ">=1.12", markers = "platform_python_implementation != \"PyPy\""} @@ -1188,7 +1190,6 @@ description = "cryptography is a package which provides cryptographic recipes an optional = false python-versions = "!=3.9.0,!=3.9.1,>=3.8" groups = ["main", "dev", "proxy-dev"] -markers = "python_version >= \"3.10\"" files = [ {file = "cryptography-46.0.3-cp311-abi3-macosx_10_9_universal2.whl", hash = "sha256:109d4ddfadf17e8e7779c39f9b18111a09efb969a301a31e987416a0191ed93a"}, {file = "cryptography-46.0.3-cp311-abi3-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:09859af8466b69bc3c27bdf4f5d84a665e0f7ab5088412e9e2ec49758eca5cbc"}, @@ -1245,6 +1246,7 @@ files = [ {file = "cryptography-46.0.3-pp311-pypy311_pp73-win_amd64.whl", hash = "sha256:6b5063083824e5509fdba180721d55909ffacccc8adbec85268b48439423d78c"}, {file = "cryptography-46.0.3.tar.gz", hash = "sha256:a8b17438104fed022ce745b362294d9ce35b4c2e45c1d958ad4a4b019285f4a1"}, ] +markers = {main = "python_version >= \"3.10\" and (extra == \"proxy\" or extra == \"extra-proxy\" or extra == \"mlflow\")", dev = "python_version >= \"3.10\"", proxy-dev = "python_version >= \"3.10\""} [package.dependencies] cffi = {version = ">=2.0.0", markers = "python_full_version >= \"3.9.0\" and platform_python_implementation != \"PyPy\""} @@ -2242,11 +2244,11 @@ files = [ ] [package.dependencies] -google-api-core = {version = ">=1.34.1,<2.0.dev0 || >=2.11.dev0,<3.0.0dev", extras = ["grpc"]} -google-auth = ">=2.14.1,<2.24.0 || >2.24.0,<2.25.0 || >2.25.0,<3.0.0dev" -grpc-google-iam-v1 = ">=0.12.4,<1.0.0dev" -proto-plus = ">=1.22.3,<2.0.0dev" -protobuf = ">=3.20.2,<4.21.0 || >4.21.0,<4.21.1 || >4.21.1,<4.21.2 || >4.21.2,<4.21.3 || >4.21.3,<4.21.4 || >4.21.4,<4.21.5 || >4.21.5,<6.0.0dev" +google-api-core = {version = ">=1.34.1,<2.0.dev0 || >=2.11.dev0,<3.0.0.dev0", extras = ["grpc"]} +google-auth = ">=2.14.1,<2.24.0 || >2.24.0,<2.25.0 || >2.25.0,<3.0.0.dev0" +grpc-google-iam-v1 = ">=0.12.4,<1.0.0.dev0" +proto-plus = ">=1.22.3,<2.0.0.dev0" +protobuf = ">=3.20.2,<4.21.0 || >4.21.0,<4.21.1 || >4.21.1,<4.21.2 || >4.21.2,<4.21.3 || >4.21.3,<4.21.4 || >4.21.4,<4.21.5 || >4.21.5,<6.0.0.dev0" [[package]] name = "google-cloud-resource-manager" @@ -3249,7 +3251,7 @@ files = [ [package.dependencies] attrs = ">=22.2.0" -jsonschema-specifications = ">=2023.03.6" +jsonschema-specifications = ">=2023.3.6" referencing = ">=0.28.4" rpds-py = ">=0.7.1" @@ -3426,15 +3428,15 @@ files = [ [[package]] name = "litellm-proxy-extras" -version = "0.4.29" +version = "0.4.30" description = "Additional files for the LiteLLM Proxy. Reduces the size of the main litellm package." optional = true python-versions = "!=2.7.*,!=3.0.*,!=3.1.*,!=3.2.*,!=3.3.*,!=3.4.*,!=3.5.*,!=3.6.*,!=3.7.*,>=3.8" groups = ["main"] markers = "extra == \"proxy\"" files = [ - {file = "litellm_proxy_extras-0.4.29-py3-none-any.whl", hash = "sha256:c36c1b69675c61acccc6b61dd610eb37daeb72c6fd819461cefb5b0cc7e0550f"}, - {file = "litellm_proxy_extras-0.4.29.tar.gz", hash = "sha256:1a8266911e0546f1e17e6714ca20b72e9fef47c1683f9c16399cf2d1786437a0"}, + {file = "litellm_proxy_extras-0.4.30-py3-none-any.whl", hash = "sha256:0b7df68f0968eb817462b847eaee81bba23d935adb2e84d2e342a77711887051"}, + {file = "litellm_proxy_extras-0.4.30.tar.gz", hash = "sha256:5d32f8dc3d37d36fb15ab6995fea706dd8a453ff7f12e70b47cba35e5368da10"}, ] [[package]] @@ -3913,6 +3915,7 @@ files = [ {file = "msal-1.34.0-py3-none-any.whl", hash = "sha256:f669b1644e4950115da7a176441b0e13ec2975c29528d8b9e81316023676d6e1"}, {file = "msal-1.34.0.tar.gz", hash = "sha256:76ba83b716ea5a6d75b0279c0ac353a0e05b820ca1f6682c0eb7f45190c43c2f"}, ] +markers = {main = "extra == \"proxy\" or extra == \"extra-proxy\""} [package.dependencies] cryptography = ">=2.5,<49" @@ -3933,6 +3936,7 @@ files = [ {file = "msal_extensions-1.3.1-py3-none-any.whl", hash = "sha256:96d3de4d034504e969ac5e85bae8106c8373b5c6568e4c8fa7af2eca9dbe6bca"}, {file = "msal_extensions-1.3.1.tar.gz", hash = "sha256:c5b0fd10f65ef62b5f1d62f4251d51cbcaf003fcedae8c91b040a488614be1a4"}, ] +markers = {main = "extra == \"proxy\" or extra == \"extra-proxy\""} [package.dependencies] msal = ">=1.29,<2" @@ -4183,6 +4187,7 @@ files = [ {file = "nodeenv-1.9.1-py2.py3-none-any.whl", hash = "sha256:ba11c9782d29c27c70ffbdda2d7415098754709be8a7056d79a737cd901155c9"}, {file = "nodeenv-1.9.1.tar.gz", hash = "sha256:6ec12890a2dab7946721edbfbcd91f3319c6ccc9aec47be7c7e6b7011ee6645f"}, ] +markers = {main = "extra == \"extra-proxy\""} [[package]] name = "numpy" @@ -4390,7 +4395,7 @@ files = [ {file = "opentelemetry_api-1.39.1-py3-none-any.whl", hash = "sha256:2edd8463432a7f8443edce90972169b195e7d6a05500cd29e6d13898187c9950"}, {file = "opentelemetry_api-1.39.1.tar.gz", hash = "sha256:fbde8c80e1b937a2c61f20347e91c0c18a1940cecf012d62e65a7caf08967c9c"}, ] -markers = {main = "python_version >= \"3.10\""} +markers = {main = "python_version >= \"3.10\" and extra == \"mlflow\""} [package.dependencies] importlib-metadata = ">=6.0,<8.8.0" @@ -4505,7 +4510,7 @@ files = [ {file = "opentelemetry_sdk-1.39.1-py3-none-any.whl", hash = "sha256:4d5482c478513ecb0a5d938dcc61394e647066e0cc2676bee9f3af3f3f45f01c"}, {file = "opentelemetry_sdk-1.39.1.tar.gz", hash = "sha256:cf4d4563caf7bff906c9f7967e2be22d0d6b349b908be0d90fb21c8e9c995cc6"}, ] -markers = {main = "python_version >= \"3.10\""} +markers = {main = "python_version >= \"3.10\" and extra == \"mlflow\""} [package.dependencies] opentelemetry-api = "1.39.1" @@ -4523,7 +4528,7 @@ files = [ {file = "opentelemetry_semantic_conventions-0.60b1-py3-none-any.whl", hash = "sha256:9fa8c8b0c110da289809292b0591220d3a7b53c1526a23021e977d68597893fb"}, {file = "opentelemetry_semantic_conventions-0.60b1.tar.gz", hash = "sha256:87c228b5a0669b748c76d76df6c364c369c28f1c465e50f661e39737e84bc953"}, ] -markers = {main = "python_version >= \"3.10\""} +markers = {main = "python_version >= \"3.10\" and extra == \"mlflow\""} [package.dependencies] opentelemetry-api = "1.39.1" @@ -5000,6 +5005,7 @@ files = [ {file = "prisma-0.11.0-py3-none-any.whl", hash = "sha256:22bb869e59a2968b99f3483bb417717273ffbc569fd1e9ceed95e5614cbaf53a"}, {file = "prisma-0.11.0.tar.gz", hash = "sha256:3f2f2fd2361e1ec5ff655f2a04c7860c2f2a5bc4c91f78ca9c5c6349735bf693"}, ] +markers = {main = "extra == \"extra-proxy\""} [package.dependencies] click = ">=7.1.2" @@ -5316,7 +5322,7 @@ files = [ {file = "pycparser-2.23-py3-none-any.whl", hash = "sha256:e5c6e8d3fbad53479cab09ac03729e0a9faf2bee3db8208a550daf5af81a5934"}, {file = "pycparser-2.23.tar.gz", hash = "sha256:78816d4f24add8f10a06d6f05b4d424ad9e96cfebf68a4ddc99c65c0720d00c2"}, ] -markers = {main = "implementation_name != \"PyPy\" and (platform_python_implementation != \"PyPy\" or extra == \"proxy\")", dev = "implementation_name != \"PyPy\" and platform_python_implementation != \"PyPy\"", proxy-dev = "implementation_name != \"PyPy\" and platform_python_implementation != \"PyPy\""} +markers = {main = "implementation_name != \"PyPy\" and (platform_python_implementation != \"PyPy\" or extra == \"proxy\") and (python_version >= \"3.10\" or extra == \"proxy\" or extra == \"extra-proxy\") and (extra == \"proxy\" or extra == \"extra-proxy\" or extra == \"mlflow\")", dev = "implementation_name != \"PyPy\" and platform_python_implementation != \"PyPy\"", proxy-dev = "implementation_name != \"PyPy\" and platform_python_implementation != \"PyPy\""} [[package]] name = "pydantic" @@ -5539,6 +5545,7 @@ files = [ {file = "PyJWT-2.10.1-py3-none-any.whl", hash = "sha256:dcdd193e30abefd5debf142f9adfcdd2b58004e644f25406ffaebd50bd98dacb"}, {file = "pyjwt-2.10.1.tar.gz", hash = "sha256:3cc5772eb20009233caf06e9d8a0577824723b44e6648ee0a2aedb6cf9381953"}, ] +markers = {main = "extra == \"extra-proxy\" or extra == \"proxy\""} [package.dependencies] cryptography = {version = ">=3.4.0", optional = true, markers = "extra == \"crypto\""} @@ -6640,10 +6647,10 @@ files = [ ] [package.dependencies] -botocore = ">=1.37.4,<2.0a.0" +botocore = ">=1.37.4,<2.0a0" [package.extras] -crt = ["botocore[crt] (>=1.37.4,<2.0a.0)"] +crt = ["botocore[crt] (>=1.37.4,<2.0a0)"] [[package]] name = "scikit-learn" @@ -6876,9 +6883,9 @@ tornado = ">=6.4.2,<7" urllib3 = ">=1.26,<3" [package.extras] -all = ["boto3 (>=1.34.98,<2)", "botocore (>=1.34.110,<2)", "cohere (>=5.9.4,<6.00)", "dagger-io (>=0.1.1) ; python_version >= \"3.11\"", "fastembed (>=0.3.0,<0.4) ; python_version < \"3.13\"", "google-cloud-aiplatform (>=1.45.0,<2)", "ipykernel (>=6.25.0,<7)", "llama-cpp-python (>=0.2.28,<0.2.86) ; python_version < \"3.13\"", "mistralai (>=0.0.12,<0.1.0)", "mypy (>=1.7.1,<2)", "ollama (>=0.1.7)", "pillow (>=10.2.0,<11.0.0) ; python_version < \"3.13\"", "pinecone[asyncio] (>=7.0.0,<8.0.0)", "psycopg[binary] (>=3.1.0,<4)", "pytest (>=8.2,<9.0)", "pytest-asyncio (>=0.24.0,<0.25)", "pytest-cov (>=4.1.0,<5)", "pytest-mock (>=3.12.0,<4)", "pytest-timeout", "pytest-xdist (>=3.5.0,<4)", "python-dotenv (>=1.0.0,<2)", "qdrant-client (>=1.11.1,<2)", "requests-mock (>=1.12.1,<2)", "ruff (>=0.11.2,<0.12)", "sentence-transformers (>=5.0.0) ; python_version < \"3.13\"", "tokenizers (>=0.19) ; python_version < \"3.13\"", "torch (>=2.6.0) ; python_version < \"3.13\"", "torchvision (>=0.17.0) ; python_version < \"3.13\"", "transformers (>=4.36.2) ; python_version < \"3.13\"", "types-pyyaml (>=6.0.12.12,<7)", "types-requests (>=2.31.0,<3)"] +all = ["boto3 (>=1.34.98,<2)", "botocore (>=1.34.110,<2)", "cohere (>=5.9.4,<6.0)", "dagger-io (>=0.1.1) ; python_version >= \"3.11\"", "fastembed (>=0.3.0,<0.4) ; python_version < \"3.13\"", "google-cloud-aiplatform (>=1.45.0,<2)", "ipykernel (>=6.25.0,<7)", "llama-cpp-python (>=0.2.28,<0.2.86) ; python_version < \"3.13\"", "mistralai (>=0.0.12,<0.1.0)", "mypy (>=1.7.1,<2)", "ollama (>=0.1.7)", "pillow (>=10.2.0,<11.0.0) ; python_version < \"3.13\"", "pinecone[asyncio] (>=7.0.0,<8.0.0)", "psycopg[binary] (>=3.1.0,<4)", "pytest (>=8.2,<9.0)", "pytest-asyncio (>=0.24.0,<0.25)", "pytest-cov (>=4.1.0,<5)", "pytest-mock (>=3.12.0,<4)", "pytest-timeout", "pytest-xdist (>=3.5.0,<4)", "python-dotenv (>=1.0.0,<2)", "qdrant-client (>=1.11.1,<2)", "requests-mock (>=1.12.1,<2)", "ruff (>=0.11.2,<0.12)", "sentence-transformers (>=5.0.0) ; python_version < \"3.13\"", "tokenizers (>=0.19) ; python_version < \"3.13\"", "torch (>=2.6.0) ; python_version < \"3.13\"", "torchvision (>=0.17.0) ; python_version < \"3.13\"", "transformers (>=4.36.2) ; python_version < \"3.13\"", "types-pyyaml (>=6.0.12.12,<7)", "types-requests (>=2.31.0,<3)"] bedrock = ["boto3 (>=1.34.98,<2)", "botocore (>=1.34.110,<2)"] -cohere = ["cohere (>=5.9.4,<6.00)"] +cohere = ["cohere (>=5.9.4,<6.0)"] dev = ["dagger-io (>=0.1.1) ; python_version >= \"3.11\"", "ipykernel (>=6.25.0,<7)", "mypy (>=1.7.1,<2)", "pytest (>=8.2,<9.0)", "pytest-asyncio (>=0.24.0,<0.25)", "pytest-cov (>=4.1.0,<5)", "pytest-mock (>=3.12.0,<4)", "pytest-timeout", "pytest-xdist (>=3.5.0,<4)", "python-dotenv (>=1.0.0,<2)", "requests-mock (>=1.12.1,<2)", "ruff (>=0.11.2,<0.12)", "types-pyyaml (>=6.0.12.12,<7)", "types-requests (>=2.31.0,<3)"] docs = ["pydoc-markdown (>=4.8.2) ; python_version < \"3.12\""] fastembed = ["fastembed (>=0.3.0,<0.4) ; python_version < \"3.13\""] @@ -7722,6 +7729,7 @@ files = [ {file = "tomlkit-0.13.3-py3-none-any.whl", hash = "sha256:c89c649d79ee40629a9fda55f8ace8c6a1b42deb912b2a8fd8d942ddadb606b0"}, {file = "tomlkit-0.13.3.tar.gz", hash = "sha256:430cf247ee57df2b94ee3fbe588e71d362a941ebb545dec29b53961d61add2a1"}, ] +markers = {main = "extra == \"extra-proxy\""} [[package]] name = "tornado" @@ -8490,4 +8498,4 @@ utils = ["numpydoc"] [metadata] lock-version = "2.1" python-versions = ">=3.9,<4.0" -content-hash = "95fd27dc139d0e52e70093220c50582f16c78e5977ec77f4297f50a30df964c6" +content-hash = "e5447e14dd37e324ac07a8fc6286d27e9a0d355ed93ebb24fc11e3f5df12fd3e" From b982542c6c5a88412c6a771a2ad9d83a7cbdbb4e Mon Sep 17 00:00:00 2001 From: yuneng-jiang Date: Wed, 4 Feb 2026 20:05:10 -0800 Subject: [PATCH 17/21] fixing build --- .../MCPSemanticFilterSettings.tsx | 7 ++----- 1 file changed, 2 insertions(+), 5 deletions(-) diff --git a/ui/litellm-dashboard/src/components/Settings/AdminSettings/MCPSemanticFilterSettings/MCPSemanticFilterSettings.tsx b/ui/litellm-dashboard/src/components/Settings/AdminSettings/MCPSemanticFilterSettings/MCPSemanticFilterSettings.tsx index 6e669f74ab3..d24c14a8e86 100644 --- a/ui/litellm-dashboard/src/components/Settings/AdminSettings/MCPSemanticFilterSettings/MCPSemanticFilterSettings.tsx +++ b/ui/litellm-dashboard/src/components/Settings/AdminSettings/MCPSemanticFilterSettings/MCPSemanticFilterSettings.tsx @@ -41,13 +41,12 @@ export default function MCPSemanticFilterSettings({ accessToken }: MCPSemanticFi const [isDirty, setIsDirty] = useState(false); const [embeddingModels, setEmbeddingModels] = useState([]); const [loadingModels, setLoadingModels] = useState(true); - + // Test section state const [testQuery, setTestQuery] = useState(""); const [testModel, setTestModel] = useState("gpt-4o"); const [testResult, setTestResult] = useState(null); const [isTesting, setIsTesting] = useState(false); - const [showCurl, setShowCurl] = useState(false); const schema = data?.field_schema; const values = data?.values ?? {}; @@ -194,7 +193,7 @@ export default function MCPSemanticFilterSettings({ accessToken }: MCPSemanticFi > - + {schema?.properties?.enabled?.description} @@ -299,8 +298,6 @@ export default function MCPSemanticFilterSettings({ accessToken }: MCPSemanticFi onTest={handleTest} filterEnabled={!!values.enabled} testResult={testResult} - showCurl={showCurl} - setShowCurl={setShowCurl} curlCommand={getCurlCommand(testModel, testQuery)} /> From 0f177a3b01a92056366a2e9c4deecb62fa2e5b85 Mon Sep 17 00:00:00 2001 From: Sameer Kankute Date: Thu, 5 Feb 2026 09:40:21 +0530 Subject: [PATCH 18/21] Fix: test_team_update_sc_2 --- ...odel_prices_and_context_window_backup.json | 25 +++++++++++++++++++ tests/test_team.py | 1 + 2 files changed, 26 insertions(+) diff --git a/litellm/model_prices_and_context_window_backup.json b/litellm/model_prices_and_context_window_backup.json index 6d399d25bf6..d3038d13a1e 100644 --- a/litellm/model_prices_and_context_window_backup.json +++ b/litellm/model_prices_and_context_window_backup.json @@ -24419,6 +24419,31 @@ "supports_tool_choice": true, "supports_function_calling": true }, + "openrouter/qwen/qwen3-235b-a22b-2507": { + "input_cost_per_token": 7.1e-08, + "litellm_provider": "openrouter", + "max_input_tokens": 262144, + "max_output_tokens": 262144, + "max_tokens": 262144, + "mode": "chat", + "output_cost_per_token": 1e-07, + "source": "https://openrouter.ai/qwen/qwen3-235b-a22b-2507", + "supports_function_calling": true, + "supports_tool_choice": true + }, + "openrouter/qwen/qwen3-235b-a22b-thinking-2507": { + "input_cost_per_token": 1.1e-07, + "litellm_provider": "openrouter", + "max_input_tokens": 262144, + "max_output_tokens": 262144, + "max_tokens": 262144, + "mode": "chat", + "output_cost_per_token": 6e-07, + "source": "https://openrouter.ai/qwen/qwen3-235b-a22b-thinking-2507", + "supports_function_calling": true, + "supports_reasoning": true, + "supports_tool_choice": true + }, "openrouter/switchpoint/router": { "input_cost_per_token": 8.5e-07, "litellm_provider": "openrouter", diff --git a/tests/test_team.py b/tests/test_team.py index d67c5e670f4..275181590c5 100644 --- a/tests/test_team.py +++ b/tests/test_team.py @@ -532,6 +532,7 @@ async def test_team_update_sc_2(): or k == "object_permission" or k == "litellm_model_table" or k == "policies" + or k == "allow_team_guardrail_config" ): pass else: From 5e8c7f0de121cea6e18c190c01036fccd113516a Mon Sep 17 00:00:00 2001 From: Sameer Kankute Date: Thu, 5 Feb 2026 09:44:05 +0530 Subject: [PATCH 19/21] Fix mypy issues --- litellm/proxy/proxy_server.py | 1 + litellm/proxy_auth/credentials.py | 2 +- 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/litellm/proxy/proxy_server.py b/litellm/proxy/proxy_server.py index 022626e2992..637893872d9 100644 --- a/litellm/proxy/proxy_server.py +++ b/litellm/proxy/proxy_server.py @@ -1864,6 +1864,7 @@ class ProxyConfig: def __init__(self) -> None: self.config: Dict[str, Any] = {} + self._last_semantic_filter_config: Optional[Dict[str, Any]] = None def is_yaml(self, config_file_path: str) -> bool: if not os.path.isfile(config_file_path): diff --git a/litellm/proxy_auth/credentials.py b/litellm/proxy_auth/credentials.py index cddaf1278f9..103b0088d80 100644 --- a/litellm/proxy_auth/credentials.py +++ b/litellm/proxy_auth/credentials.py @@ -79,7 +79,7 @@ class AzureADCredential: credential: An azure-identity credential object. If None, DefaultAzureCredential will be used on first token request. """ - self._credential = credential + self._credential: Any = credential self._initialized = credential is not None def get_token(self, scope: str) -> AccessToken: From 5422a5962e8340d37ebfbac98083afb14f0bce58 Mon Sep 17 00:00:00 2001 From: Sameer Kankute Date: Thu, 5 Feb 2026 09:47:05 +0530 Subject: [PATCH 20/21] Fix test_route_a2a_model_bypasses_router --- tests/test_litellm/proxy/test_route_a2a_models.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/test_litellm/proxy/test_route_a2a_models.py b/tests/test_litellm/proxy/test_route_a2a_models.py index e8d89c0c7eb..1288a9b2c9f 100644 --- a/tests/test_litellm/proxy/test_route_a2a_models.py +++ b/tests/test_litellm/proxy/test_route_a2a_models.py @@ -55,7 +55,7 @@ async def test_route_a2a_model_bypasses_router(): with patch("litellm.acompletion", mock_acompletion): with patch( - "litellm.proxy.agent_endpoints.a2a_routing.global_agent_registry", + "litellm.proxy.agent_endpoints.agent_registry.global_agent_registry", mock_registry, ): result = await route_request( From 0ce1bfe26a1ead30a87cbde2e660b468c4fd6510 Mon Sep 17 00:00:00 2001 From: Sameer Kankute Date: Thu, 5 Feb 2026 10:44:48 +0530 Subject: [PATCH 21/21] =?UTF-8?q?bump:=20version=201.81.7=20=E2=86=92=201.?= =?UTF-8?q?81.8?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- pyproject.toml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/pyproject.toml b/pyproject.toml index 80841912c54..0d0968ee8ee 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -1,6 +1,6 @@ [tool.poetry] name = "litellm" -version = "1.81.7" +version = "1.81.8" description = "Library to easily interface with LLM API providers" authors = ["BerriAI"] license = "MIT" @@ -174,7 +174,7 @@ requires = ["poetry-core", "wheel"] build-backend = "poetry.core.masonry.api" [tool.commitizen] -version = "1.81.7" +version = "1.81.8" version_files = [ "pyproject.toml:^version" ]