diff --git a/litellm/llms/manus/responses/transformation.py b/litellm/llms/manus/responses/transformation.py index 7a72f23dd5..8e0a4a5a30 100644 --- a/litellm/llms/manus/responses/transformation.py +++ b/litellm/llms/manus/responses/transformation.py @@ -94,9 +94,11 @@ class ManusResponsesAPIConfig(OpenAIResponsesAPIConfig): ) # Manus uses API_KEY header, not Authorization: Bearer + # Content-Type is required for all requests (including GET) headers.update( { "API_KEY": api_key, + "Content-Type": "application/json", } ) return headers @@ -164,8 +166,9 @@ class ManusResponsesAPIConfig(OpenAIResponsesAPIConfig): if extra_body: base_request.update(extra_body) - # Avoid logging potentially sensitive agent_profile value - verbose_logger.debug("Manus: Using task_mode=agent") + verbose_logger.debug( + f"Manus: Using agent_profile={agent_profile}, task_mode=agent" + ) return base_request diff --git a/tests/llm_responses_api_testing/test_manus_responses_api.py b/tests/llm_responses_api_testing/test_manus_responses_api.py index 338a956bfe..4f64980d26 100644 --- a/tests/llm_responses_api_testing/test_manus_responses_api.py +++ b/tests/llm_responses_api_testing/test_manus_responses_api.py @@ -20,96 +20,33 @@ from litellm.llms.custom_httpx.http_handler import AsyncHTTPHandler from base_responses_api import BaseResponsesAPITest -# class TestManusResponsesAPITest(BaseResponsesAPITest): -# def get_base_completion_call_args(self): -# return { -# "model": "manus/manus-1.6", -# "api_key": os.getenv("MANUS_API_KEY"), -# } - -# @pytest.mark.parametrize("sync_mode", [True, False]) -# @pytest.mark.asyncio -# async def test_basic_openai_responses_delete_endpoint(self, sync_mode): -# pytest.skip("DELETE responses is not supported for Manus") - -# @pytest.mark.parametrize("sync_mode", [True, False]) -# @pytest.mark.asyncio -# async def test_basic_openai_responses_streaming_delete_endpoint(self, sync_mode): -# pytest.skip("DELETE responses is not supported for Manus") - -# # GET responses is now supported for Manus -# @pytest.mark.parametrize("sync_mode", [True, False]) -# @pytest.mark.asyncio -# async def test_basic_openai_responses_get_endpoint(self, sync_mode): -# pytest.skip("GET responses is not supported for Manus") - -# @pytest.mark.parametrize("sync_mode", [True, False]) -# @pytest.mark.asyncio -# async def test_basic_openai_responses_cancel_endpoint(self, sync_mode): -# pytest.skip("CANCEL responses is not supported for Manus") - -# @pytest.mark.parametrize("sync_mode", [True, False]) -# @pytest.mark.asyncio -# async def test_cancel_responses_invalid_response_id(self, sync_mode): -# pytest.skip("CANCEL responses is not supported for Manus") - -# @pytest.mark.asyncio -# async def test_multiturn_responses_api(self): -# pytest.skip("Multiturn responses is not supported for Manus") - - -# @pytest.mark.asyncio -# async def test_manus_responses_api_with_agent_profile(): -# """ -# Test that Manus API correctly extracts agent profile from model name -# and includes task_mode and agent_profile in the request. -# """ -# litellm._turn_on_debug() +@pytest.mark.asyncio +async def test_manus_responses_api_with_agent_profile(): + """ + Test that Manus API correctly extracts agent profile from model name + and includes task_mode and agent_profile in the request. + """ + litellm._turn_on_debug() -# response = await litellm.aresponses( -# model="manus/manus-1.6", -# input="What's the color of the sky?", -# api_key=os.getenv("MANUS_API_KEY"), -# max_output_tokens=50, -# ) + response = await litellm.aresponses( + model="manus/manus-1.6-lite", + input="What's the color of the sky?", + api_key=os.getenv("MANUS_API_KEY"), + max_output_tokens=50, + ) -# print("Manus response=", json.dumps(response, indent=4, default=str)) + print("Manus response=", json.dumps(response, indent=4, default=str)) + + ## Get the status of the response + got_response = await litellm.aget_responses(response_id=response.id) + print("GET API MANUS RESPONSE=", json.dumps(got_response, indent=4, default=str)) + if got_response.status == "completed": + assert got_response.output is not None + assert len(got_response.output) > 0 + else: + # Manus can return "running" or "pending" status + assert got_response.status in ["running", "pending"] + assert got_response.id is not None -# # Validate response structure -# assert isinstance(response, ResponsesAPIResponse), "Response should be ResponsesAPIResponse" -# assert response.id is not None, "Response should have an ID" -# assert response.status in ["running", "completed", "pending"], f"Status should be valid, got {response.status}" - -# # Check that metadata includes Manus-specific fields -# if response.metadata: -# assert "task_id" in response.metadata or "task_url" in response.metadata, ( -# "Manus response should include task_id or task_url in metadata" -# ) -# @pytest.mark.asyncio -# async def test_manus_responses_api_different_agent_profiles(): -# """ -# Test that different agent profiles work correctly. -# """ -# litellm._turn_on_debug() - -# # Test with different agent profile variants -# agent_profiles = ["manus-1.6", "manus-1.6-lite", "manus-1.6-max"] - -# for profile in agent_profiles: -# try: -# response = await litellm.aresponses( -# model=f"manus/{profile}", -# input="Hello", -# api_key=os.getenv("MANUS_API_KEY"), -# max_output_tokens=20, -# ) - -# assert response.id is not None, f"Response for {profile} should have an ID" -# print(f"✓ {profile} works: {response.id}") -# except Exception as e: -# # Some profiles might not be available, that's okay -# print(f"⚠ {profile} not available: {e}") -# pass -