commit
3c4d4e19ea
|
Before Width: | Height: | Size: 1.7 MiB |
|
After Width: | Height: | Size: 36 KiB |
@ -0,0 +1,145 @@
|
||||
import os
|
||||
import traceback
|
||||
from typing import Any, Dict, List
|
||||
|
||||
import httpx
|
||||
from loguru import logger
|
||||
|
||||
|
||||
def add_prompt_to_marketplace(
|
||||
name: str = None,
|
||||
prompt: str = None,
|
||||
description: str = None,
|
||||
use_cases: List[Dict[str, str]] = None,
|
||||
tags: str = None,
|
||||
is_free: bool = True,
|
||||
price_usd: float = 0.0,
|
||||
category: str = "research",
|
||||
timeout: float = 30.0,
|
||||
) -> Dict[str, Any]:
|
||||
"""
|
||||
Add a prompt to the Swarms marketplace.
|
||||
|
||||
Args:
|
||||
name: The name of the prompt.
|
||||
prompt: The prompt text/template.
|
||||
description: A description of what the prompt does.
|
||||
use_cases: List of dictionaries with 'title' and 'description' keys
|
||||
describing use cases for the prompt.
|
||||
tags: Comma-separated string of tags for the prompt.
|
||||
is_free: Whether the prompt is free or paid.
|
||||
price_usd: Price in USD (ignored if is_free is True).
|
||||
category: Category of the prompt (e.g., "content", "coding", etc.).
|
||||
timeout: Request timeout in seconds. Defaults to 30.0.
|
||||
|
||||
Returns:
|
||||
Dictionary containing the API response.
|
||||
|
||||
Raises:
|
||||
httpx.HTTPError: If the HTTP request fails.
|
||||
httpx.RequestError: If there's an error making the request.
|
||||
"""
|
||||
try:
|
||||
url = "https://swarms.world/api/add-prompt"
|
||||
api_key = os.getenv("SWARMS_API_KEY")
|
||||
|
||||
if api_key is None or api_key.strip() == "":
|
||||
raise ValueError(
|
||||
"Swarms API key is not set. Please set the SWARMS_API_KEY environment variable. "
|
||||
"You can get your key here: https://swarms.world/platform/api-keys"
|
||||
)
|
||||
|
||||
# Log that we have an API key (without exposing it)
|
||||
logger.debug(
|
||||
f"Using API key (length: {len(api_key)} characters)"
|
||||
)
|
||||
|
||||
# Validate required fields
|
||||
if name is None:
|
||||
raise ValueError("name is required")
|
||||
if prompt is None:
|
||||
raise ValueError("prompt is required")
|
||||
if description is None:
|
||||
raise ValueError("description is required")
|
||||
if category is None:
|
||||
raise ValueError("category is required")
|
||||
if use_cases is None:
|
||||
raise ValueError("use_cases is required")
|
||||
|
||||
headers = {
|
||||
"Authorization": f"Bearer {api_key}",
|
||||
"Content-Type": "application/json",
|
||||
}
|
||||
|
||||
data = {
|
||||
"name": name,
|
||||
"prompt": prompt,
|
||||
"description": description,
|
||||
"useCases": use_cases or [],
|
||||
"tags": tags or "",
|
||||
"is_free": is_free,
|
||||
"price_usd": price_usd,
|
||||
"category": category,
|
||||
}
|
||||
|
||||
with httpx.Client(timeout=timeout) as client:
|
||||
response = client.post(url, json=data, headers=headers)
|
||||
|
||||
# Try to get response body for better error messages
|
||||
try:
|
||||
response_body = response.json()
|
||||
except Exception:
|
||||
response_body = response.text
|
||||
|
||||
if response.status_code >= 400:
|
||||
error_msg = f"HTTP {response.status_code}: {response.reason_phrase}"
|
||||
if response_body:
|
||||
error_msg += f"\nResponse: {response_body}"
|
||||
logger.error(
|
||||
f"Error adding prompt to marketplace: {error_msg}"
|
||||
)
|
||||
|
||||
response.raise_for_status()
|
||||
logger.info(
|
||||
f"Prompt Name: {name} Successfully added to marketplace"
|
||||
)
|
||||
return response_body
|
||||
except httpx.HTTPStatusError as e:
|
||||
logger.error(f"HTTP error adding prompt to marketplace: {e}")
|
||||
if hasattr(e, "response") and e.response is not None:
|
||||
try:
|
||||
error_body = e.response.json()
|
||||
logger.error(f"Error response body: {error_body}")
|
||||
|
||||
# Provide helpful error message for authentication failures
|
||||
if (
|
||||
e.response.status_code == 401
|
||||
or e.response.status_code == 500
|
||||
):
|
||||
if isinstance(error_body, dict):
|
||||
if (
|
||||
"authentication"
|
||||
in str(error_body).lower()
|
||||
or "auth" in str(error_body).lower()
|
||||
):
|
||||
logger.error(
|
||||
"Authentication failed. Please check:\n"
|
||||
"1. Your SWARMS_API_KEY environment variable is set correctly\n"
|
||||
"2. Your API key is valid and not expired\n"
|
||||
"3. You can verify your key at: https://swarms.world/platform/api-keys"
|
||||
)
|
||||
except Exception:
|
||||
logger.error(
|
||||
f"Error response text: {e.response.text}"
|
||||
)
|
||||
raise
|
||||
except httpx.RequestError as e:
|
||||
logger.error(
|
||||
f"Request error adding prompt to marketplace: {e}"
|
||||
)
|
||||
raise
|
||||
except Exception as e:
|
||||
logger.error(
|
||||
f"Error adding prompt to marketplace: {e} Traceback: {traceback.format_exc()}"
|
||||
)
|
||||
raise
|
||||
@ -0,0 +1,306 @@
|
||||
"""
|
||||
Pytest tests for swarms_marketplace_utils module.
|
||||
"""
|
||||
import os
|
||||
from unittest.mock import Mock, patch
|
||||
|
||||
import pytest
|
||||
|
||||
from swarms.utils.swarms_marketplace_utils import (
|
||||
add_prompt_to_marketplace,
|
||||
)
|
||||
|
||||
|
||||
class TestAddPromptToMarketplace:
|
||||
"""Test cases for add_prompt_to_marketplace function."""
|
||||
|
||||
@patch.dict(os.environ, {"SWARMS_API_KEY": "test_api_key_12345"})
|
||||
@patch("swarms.utils.swarms_marketplace_utils.httpx.Client")
|
||||
def test_add_prompt_success(self, mock_client_class):
|
||||
"""Test successful addition of prompt to marketplace."""
|
||||
# Mock response
|
||||
mock_response = Mock()
|
||||
mock_response.status_code = 200
|
||||
mock_response.json.return_value = {
|
||||
"id": "123",
|
||||
"name": "Blood Analysis Agent",
|
||||
"status": "success",
|
||||
}
|
||||
mock_response.text = ""
|
||||
mock_response.raise_for_status = Mock()
|
||||
|
||||
# Mock client
|
||||
mock_client = Mock()
|
||||
mock_client.__enter__ = Mock(return_value=mock_client)
|
||||
mock_client.__exit__ = Mock(return_value=False)
|
||||
mock_client.post.return_value = mock_response
|
||||
mock_client_class.return_value = mock_client
|
||||
|
||||
# Call function
|
||||
result = add_prompt_to_marketplace(
|
||||
name="Blood Analysis Agent",
|
||||
prompt="You are a blood analysis agent that can analyze blood samples and provide a report on the results.",
|
||||
description="A blood analysis agent that can analyze blood samples and provide a report on the results.",
|
||||
use_cases=[
|
||||
{
|
||||
"title": "Blood Analysis",
|
||||
"description": "Analyze blood samples and provide a report on the results.",
|
||||
}
|
||||
],
|
||||
tags="blood, analysis, report",
|
||||
category="research",
|
||||
)
|
||||
|
||||
# Assertions
|
||||
assert result["id"] == "123"
|
||||
assert result["name"] == "Blood Analysis Agent"
|
||||
assert result["status"] == "success"
|
||||
mock_client.post.assert_called_once()
|
||||
call_args = mock_client.post.call_args
|
||||
assert call_args[0][0] == "https://swarms.world/api/add-prompt"
|
||||
assert call_args[1]["headers"]["Authorization"] == "Bearer test_api_key_12345"
|
||||
assert call_args[1]["json"]["name"] == "Blood Analysis Agent"
|
||||
assert call_args[1]["json"]["category"] == "research"
|
||||
|
||||
@patch.dict(os.environ, {"SWARMS_API_KEY": "test_api_key_12345"})
|
||||
@patch("swarms.utils.swarms_marketplace_utils.httpx.Client")
|
||||
def test_add_prompt_with_all_parameters(self, mock_client_class):
|
||||
"""Test adding prompt with all optional parameters."""
|
||||
# Mock response
|
||||
mock_response = Mock()
|
||||
mock_response.status_code = 200
|
||||
mock_response.json.return_value = {"id": "456", "status": "success"}
|
||||
mock_response.text = ""
|
||||
mock_response.raise_for_status = Mock()
|
||||
|
||||
# Mock client
|
||||
mock_client = Mock()
|
||||
mock_client.__enter__ = Mock(return_value=mock_client)
|
||||
mock_client.__exit__ = Mock(return_value=False)
|
||||
mock_client.post.return_value = mock_response
|
||||
mock_client_class.return_value = mock_client
|
||||
|
||||
# Call function with all parameters
|
||||
result = add_prompt_to_marketplace(
|
||||
name="Test Prompt",
|
||||
prompt="Test prompt text",
|
||||
description="Test description",
|
||||
use_cases=[{"title": "Use Case 1", "description": "Description 1"}],
|
||||
tags="tag1, tag2",
|
||||
is_free=False,
|
||||
price_usd=9.99,
|
||||
category="coding",
|
||||
timeout=60.0,
|
||||
)
|
||||
|
||||
# Assertions
|
||||
assert result["id"] == "456"
|
||||
call_args = mock_client.post.call_args
|
||||
json_data = call_args[1]["json"]
|
||||
assert json_data["is_free"] is False
|
||||
assert json_data["price_usd"] == 9.99
|
||||
assert json_data["category"] == "coding"
|
||||
assert json_data["tags"] == "tag1, tag2"
|
||||
|
||||
def test_add_prompt_missing_api_key(self):
|
||||
"""Test that missing API key raises ValueError."""
|
||||
with patch.dict(os.environ, {}, clear=True):
|
||||
with pytest.raises(ValueError, match="Swarms API key is not set"):
|
||||
add_prompt_to_marketplace(
|
||||
name="Test",
|
||||
prompt="Test prompt",
|
||||
description="Test description",
|
||||
use_cases=[],
|
||||
category="research",
|
||||
)
|
||||
|
||||
def test_add_prompt_empty_api_key(self):
|
||||
"""Test that empty API key raises ValueError."""
|
||||
with patch.dict(os.environ, {"SWARMS_API_KEY": ""}):
|
||||
with pytest.raises(ValueError, match="Swarms API key is not set"):
|
||||
add_prompt_to_marketplace(
|
||||
name="Test",
|
||||
prompt="Test prompt",
|
||||
description="Test description",
|
||||
use_cases=[],
|
||||
category="research",
|
||||
)
|
||||
|
||||
def test_add_prompt_missing_name(self):
|
||||
"""Test that missing name raises ValueError."""
|
||||
with patch.dict(os.environ, {"SWARMS_API_KEY": "test_key"}):
|
||||
with pytest.raises(ValueError, match="name is required"):
|
||||
add_prompt_to_marketplace(
|
||||
name=None,
|
||||
prompt="Test prompt",
|
||||
description="Test description",
|
||||
use_cases=[],
|
||||
category="research",
|
||||
)
|
||||
|
||||
def test_add_prompt_missing_prompt(self):
|
||||
"""Test that missing prompt raises ValueError."""
|
||||
with patch.dict(os.environ, {"SWARMS_API_KEY": "test_key"}):
|
||||
with pytest.raises(ValueError, match="prompt is required"):
|
||||
add_prompt_to_marketplace(
|
||||
name="Test",
|
||||
prompt=None,
|
||||
description="Test description",
|
||||
use_cases=[],
|
||||
category="research",
|
||||
)
|
||||
|
||||
def test_add_prompt_missing_description(self):
|
||||
"""Test that missing description raises ValueError."""
|
||||
with patch.dict(os.environ, {"SWARMS_API_KEY": "test_key"}):
|
||||
with pytest.raises(ValueError, match="description is required"):
|
||||
add_prompt_to_marketplace(
|
||||
name="Test",
|
||||
prompt="Test prompt",
|
||||
description=None,
|
||||
use_cases=[],
|
||||
category="research",
|
||||
)
|
||||
|
||||
def test_add_prompt_missing_category(self):
|
||||
"""Test that missing category raises ValueError."""
|
||||
with patch.dict(os.environ, {"SWARMS_API_KEY": "test_key"}):
|
||||
with pytest.raises(ValueError, match="category is required"):
|
||||
add_prompt_to_marketplace(
|
||||
name="Test",
|
||||
prompt="Test prompt",
|
||||
description="Test description",
|
||||
use_cases=[],
|
||||
category=None,
|
||||
)
|
||||
|
||||
def test_add_prompt_missing_use_cases(self):
|
||||
"""Test that missing use_cases raises ValueError."""
|
||||
with patch.dict(os.environ, {"SWARMS_API_KEY": "test_key"}):
|
||||
with pytest.raises(ValueError, match="use_cases is required"):
|
||||
add_prompt_to_marketplace(
|
||||
name="Test",
|
||||
prompt="Test prompt",
|
||||
description="Test description",
|
||||
use_cases=None,
|
||||
category="research",
|
||||
)
|
||||
|
||||
@patch.dict(os.environ, {"SWARMS_API_KEY": "test_api_key_12345"})
|
||||
@patch("swarms.utils.swarms_marketplace_utils.httpx.Client")
|
||||
def test_add_prompt_http_error(self, mock_client_class):
|
||||
"""Test handling of HTTP error responses."""
|
||||
# Mock response with error
|
||||
mock_response = Mock()
|
||||
mock_response.status_code = 400
|
||||
mock_response.reason_phrase = "Bad Request"
|
||||
mock_response.json.return_value = {"error": "Invalid request"}
|
||||
mock_response.text = '{"error": "Invalid request"}'
|
||||
mock_response.raise_for_status.side_effect = Exception("HTTP 400")
|
||||
|
||||
# Mock client
|
||||
mock_client = Mock()
|
||||
mock_client.__enter__ = Mock(return_value=mock_client)
|
||||
mock_client.__exit__ = Mock(return_value=False)
|
||||
mock_client.post.return_value = mock_response
|
||||
mock_client_class.return_value = mock_client
|
||||
|
||||
# Call function and expect exception
|
||||
with pytest.raises(Exception):
|
||||
add_prompt_to_marketplace(
|
||||
name="Test",
|
||||
prompt="Test prompt",
|
||||
description="Test description",
|
||||
use_cases=[],
|
||||
category="research",
|
||||
)
|
||||
|
||||
@patch.dict(os.environ, {"SWARMS_API_KEY": "test_api_key_12345"})
|
||||
@patch("swarms.utils.swarms_marketplace_utils.httpx.Client")
|
||||
def test_add_prompt_authentication_error(self, mock_client_class):
|
||||
"""Test handling of authentication errors."""
|
||||
# Mock response with 401 error
|
||||
mock_response = Mock()
|
||||
mock_response.status_code = 401
|
||||
mock_response.reason_phrase = "Unauthorized"
|
||||
mock_response.json.return_value = {
|
||||
"error": "Authentication failed"
|
||||
}
|
||||
mock_response.text = '{"error": "Authentication failed"}'
|
||||
mock_response.raise_for_status.side_effect = Exception("HTTP 401")
|
||||
|
||||
# Mock client
|
||||
mock_client = Mock()
|
||||
mock_client.__enter__ = Mock(return_value=mock_client)
|
||||
mock_client.__exit__ = Mock(return_value=False)
|
||||
mock_client.post.return_value = mock_response
|
||||
mock_client_class.return_value = mock_client
|
||||
|
||||
# Call function and expect exception
|
||||
with pytest.raises(Exception):
|
||||
add_prompt_to_marketplace(
|
||||
name="Test",
|
||||
prompt="Test prompt",
|
||||
description="Test description",
|
||||
use_cases=[],
|
||||
category="research",
|
||||
)
|
||||
|
||||
@patch.dict(os.environ, {"SWARMS_API_KEY": "test_api_key_12345"})
|
||||
@patch("swarms.utils.swarms_marketplace_utils.httpx.Client")
|
||||
def test_add_prompt_with_empty_tags(self, mock_client_class):
|
||||
"""Test adding prompt with empty tags."""
|
||||
# Mock response
|
||||
mock_response = Mock()
|
||||
mock_response.status_code = 200
|
||||
mock_response.json.return_value = {"id": "789", "status": "success"}
|
||||
mock_response.text = ""
|
||||
mock_response.raise_for_status = Mock()
|
||||
|
||||
# Mock client
|
||||
mock_client = Mock()
|
||||
mock_client.__enter__ = Mock(return_value=mock_client)
|
||||
mock_client.__exit__ = Mock(return_value=False)
|
||||
mock_client.post.return_value = mock_response
|
||||
mock_client_class.return_value = mock_client
|
||||
|
||||
# Call function with empty tags
|
||||
result = add_prompt_to_marketplace(
|
||||
name="Test",
|
||||
prompt="Test prompt",
|
||||
description="Test description",
|
||||
use_cases=[],
|
||||
tags=None,
|
||||
category="research",
|
||||
)
|
||||
|
||||
# Assertions
|
||||
assert result["id"] == "789"
|
||||
call_args = mock_client.post.call_args
|
||||
assert call_args[1]["json"]["tags"] == ""
|
||||
|
||||
@patch.dict(os.environ, {"SWARMS_API_KEY": "test_api_key_12345"})
|
||||
@patch("swarms.utils.swarms_marketplace_utils.httpx.Client")
|
||||
def test_add_prompt_request_timeout(self, mock_client_class):
|
||||
"""Test handling of request timeout."""
|
||||
# Mock client to raise timeout error
|
||||
mock_client = Mock()
|
||||
mock_client.__enter__ = Mock(return_value=mock_client)
|
||||
mock_client.__exit__ = Mock(return_value=False)
|
||||
mock_client.post.side_effect = Exception("Request timeout")
|
||||
mock_client_class.return_value = mock_client
|
||||
|
||||
# Call function and expect exception
|
||||
with pytest.raises(Exception):
|
||||
add_prompt_to_marketplace(
|
||||
name="Test",
|
||||
prompt="Test prompt",
|
||||
description="Test description",
|
||||
use_cases=[],
|
||||
category="research",
|
||||
timeout=5.0,
|
||||
)
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
pytest.main([__file__, "-v"])
|
||||
Loading…
Reference in new issue