open-swarm 0.1.1743070217__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (89) hide show
  1. open_swarm-0.1.1743070217.dist-info/METADATA +258 -0
  2. open_swarm-0.1.1743070217.dist-info/RECORD +89 -0
  3. open_swarm-0.1.1743070217.dist-info/WHEEL +5 -0
  4. open_swarm-0.1.1743070217.dist-info/entry_points.txt +3 -0
  5. open_swarm-0.1.1743070217.dist-info/licenses/LICENSE +21 -0
  6. open_swarm-0.1.1743070217.dist-info/top_level.txt +1 -0
  7. swarm/__init__.py +3 -0
  8. swarm/agent/__init__.py +7 -0
  9. swarm/agent/agent.py +49 -0
  10. swarm/apps.py +53 -0
  11. swarm/auth.py +56 -0
  12. swarm/consumers.py +141 -0
  13. swarm/core.py +326 -0
  14. swarm/extensions/__init__.py +1 -0
  15. swarm/extensions/blueprint/__init__.py +36 -0
  16. swarm/extensions/blueprint/agent_utils.py +45 -0
  17. swarm/extensions/blueprint/blueprint_base.py +562 -0
  18. swarm/extensions/blueprint/blueprint_discovery.py +112 -0
  19. swarm/extensions/blueprint/blueprint_utils.py +17 -0
  20. swarm/extensions/blueprint/common_utils.py +12 -0
  21. swarm/extensions/blueprint/django_utils.py +203 -0
  22. swarm/extensions/blueprint/interactive_mode.py +102 -0
  23. swarm/extensions/blueprint/modes/rest_mode.py +37 -0
  24. swarm/extensions/blueprint/output_utils.py +95 -0
  25. swarm/extensions/blueprint/spinner.py +91 -0
  26. swarm/extensions/cli/__init__.py +0 -0
  27. swarm/extensions/cli/blueprint_runner.py +251 -0
  28. swarm/extensions/cli/cli_args.py +88 -0
  29. swarm/extensions/cli/commands/__init__.py +0 -0
  30. swarm/extensions/cli/commands/blueprint_management.py +31 -0
  31. swarm/extensions/cli/commands/config_management.py +15 -0
  32. swarm/extensions/cli/commands/edit_config.py +77 -0
  33. swarm/extensions/cli/commands/list_blueprints.py +22 -0
  34. swarm/extensions/cli/commands/validate_env.py +57 -0
  35. swarm/extensions/cli/commands/validate_envvars.py +39 -0
  36. swarm/extensions/cli/interactive_shell.py +41 -0
  37. swarm/extensions/cli/main.py +36 -0
  38. swarm/extensions/cli/selection.py +43 -0
  39. swarm/extensions/cli/utils/discover_commands.py +32 -0
  40. swarm/extensions/cli/utils/env_setup.py +15 -0
  41. swarm/extensions/cli/utils.py +105 -0
  42. swarm/extensions/config/__init__.py +6 -0
  43. swarm/extensions/config/config_loader.py +208 -0
  44. swarm/extensions/config/config_manager.py +258 -0
  45. swarm/extensions/config/server_config.py +49 -0
  46. swarm/extensions/config/setup_wizard.py +103 -0
  47. swarm/extensions/config/utils/__init__.py +0 -0
  48. swarm/extensions/config/utils/logger.py +36 -0
  49. swarm/extensions/launchers/__init__.py +1 -0
  50. swarm/extensions/launchers/build_launchers.py +14 -0
  51. swarm/extensions/launchers/build_swarm_wrapper.py +12 -0
  52. swarm/extensions/launchers/swarm_api.py +68 -0
  53. swarm/extensions/launchers/swarm_cli.py +304 -0
  54. swarm/extensions/launchers/swarm_wrapper.py +29 -0
  55. swarm/extensions/mcp/__init__.py +1 -0
  56. swarm/extensions/mcp/cache_utils.py +36 -0
  57. swarm/extensions/mcp/mcp_client.py +341 -0
  58. swarm/extensions/mcp/mcp_constants.py +7 -0
  59. swarm/extensions/mcp/mcp_tool_provider.py +110 -0
  60. swarm/llm/chat_completion.py +195 -0
  61. swarm/messages.py +132 -0
  62. swarm/migrations/0010_initial_chat_models.py +51 -0
  63. swarm/migrations/__init__.py +0 -0
  64. swarm/models.py +45 -0
  65. swarm/repl/__init__.py +1 -0
  66. swarm/repl/repl.py +87 -0
  67. swarm/serializers.py +12 -0
  68. swarm/settings.py +189 -0
  69. swarm/tool_executor.py +239 -0
  70. swarm/types.py +126 -0
  71. swarm/urls.py +89 -0
  72. swarm/util.py +124 -0
  73. swarm/utils/color_utils.py +40 -0
  74. swarm/utils/context_utils.py +272 -0
  75. swarm/utils/general_utils.py +162 -0
  76. swarm/utils/logger.py +61 -0
  77. swarm/utils/logger_setup.py +25 -0
  78. swarm/utils/message_sequence.py +173 -0
  79. swarm/utils/message_utils.py +95 -0
  80. swarm/utils/redact.py +68 -0
  81. swarm/views/__init__.py +41 -0
  82. swarm/views/api_views.py +46 -0
  83. swarm/views/chat_views.py +76 -0
  84. swarm/views/core_views.py +118 -0
  85. swarm/views/message_views.py +40 -0
  86. swarm/views/model_views.py +135 -0
  87. swarm/views/utils.py +457 -0
  88. swarm/views/web_views.py +149 -0
  89. swarm/wsgi.py +16 -0
@@ -0,0 +1,149 @@
1
+ """
2
+ Web UI views for Open Swarm MCP Core.
3
+ Handles rendering index, blueprint pages, login, and serving config.
4
+ """
5
+ import os
6
+ import json
7
+ from pathlib import Path
8
+ from django.shortcuts import render, redirect
9
+ from django.http import JsonResponse, HttpResponse
10
+ from django.conf import settings
11
+ from django.views.decorators.csrf import csrf_exempt
12
+ from django.contrib.auth import authenticate, login
13
+ from django.contrib.auth.models import User
14
+
15
+ from swarm.utils.logger_setup import setup_logger
16
+ # Import the function to discover blueprints dynamically
17
+ from swarm.extensions.blueprint.blueprint_discovery import discover_blueprints
18
+ # Import the setting for the blueprints directory
19
+ from swarm.settings import BLUEPRINTS_DIR
20
+ # Import config loader if needed, or assume config is loaded elsewhere
21
+ from swarm.extensions.config.config_loader import load_server_config
22
+
23
+ logger = setup_logger(__name__)
24
+
25
+ @csrf_exempt
26
+ def index(request):
27
+ """Render the main index page with dynamically discovered blueprint options."""
28
+ logger.debug("Rendering index page")
29
+ try:
30
+ # Discover blueprints dynamically each time the index is loaded
31
+ # Consider caching this if performance becomes an issue
32
+ discovered_metadata = discover_blueprints(directories=[BLUEPRINTS_DIR])
33
+ blueprint_names = list(discovered_metadata.keys())
34
+ logger.debug(f"Rendering index with blueprints: {blueprint_names}")
35
+ except Exception as e:
36
+ logger.error(f"Error discovering blueprints for index page: {e}", exc_info=True)
37
+ blueprint_names = [] # Show empty list on error
38
+
39
+ context = {
40
+ "dark_mode": request.session.get('dark_mode', True),
41
+ "enable_admin": os.getenv("ENABLE_ADMIN", "false").lower() in ("true", "1", "t"),
42
+ "blueprints": blueprint_names # Use the dynamically discovered list
43
+ }
44
+ return render(request, "index.html", context)
45
+
46
+ @csrf_exempt
47
+ def blueprint_webpage(request, blueprint_name):
48
+ """Render a simple webpage for querying agents of a specific blueprint."""
49
+ logger.debug(f"Received request for blueprint webpage: '{blueprint_name}'")
50
+ try:
51
+ # Discover blueprints to check if the requested one exists
52
+ discovered_metadata = discover_blueprints(directories=[BLUEPRINTS_DIR])
53
+ if blueprint_name not in discovered_metadata:
54
+ logger.warning(f"Blueprint '{blueprint_name}' not found during discovery.")
55
+ available_blueprints = "".join(f"<li>{bp}</li>" for bp in discovered_metadata.keys())
56
+ return HttpResponse(
57
+ f"<h1>Blueprint '{blueprint_name}' not found.</h1><p>Available blueprints:</p><ul>{available_blueprints}</ul>",
58
+ status=404,
59
+ )
60
+ # Blueprint exists, render the page
61
+ context = {
62
+ "blueprint_name": blueprint_name,
63
+ "dark_mode": request.session.get('dark_mode', True),
64
+ "is_chatbot": False # Adjust if needed based on blueprint type
65
+ }
66
+ return render(request, "simple_blueprint_page.html", context)
67
+ except Exception as e:
68
+ logger.error(f"Error processing blueprint page for '{blueprint_name}': {e}", exc_info=True)
69
+ return HttpResponse("<h1>Error loading blueprint page.</h1>", status=500)
70
+
71
+
72
+ @csrf_exempt
73
+ def custom_login(request):
74
+ """Handle custom login at /accounts/login/, redirecting to 'next' URL on success."""
75
+ if request.method == "POST":
76
+ username = request.POST.get("username")
77
+ password = request.POST.get("password")
78
+ user = authenticate(request, username=username, password=password)
79
+
80
+ if user is not None:
81
+ # User authenticated successfully
82
+ login(request, user)
83
+ next_url = request.GET.get("next", "/chatbot/") # Default redirect
84
+ logger.info(f"User '{username}' logged in successfully. Redirecting to '{next_url}'.")
85
+ return redirect(next_url)
86
+ else:
87
+ # Authentication failed
88
+ logger.warning(f"Failed login attempt for user '{username}'.")
89
+ # Check if auto-login for 'testuser' is enabled (ONLY for development/testing)
90
+ enable_auth = os.getenv("ENABLE_API_AUTH", "true").lower() in ("true", "1", "t") # Default to TRUE
91
+ if not enable_auth:
92
+ logger.info("API Auth is disabled. Attempting auto-login for 'testuser'.")
93
+ try:
94
+ # Attempt to log in 'testuser' with a known password (e.g., 'testpass')
95
+ # Ensure this user/password exists in your DB or fixture
96
+ test_user = authenticate(request, username="testuser", password="testpass")
97
+ if test_user is not None:
98
+ login(request, test_user)
99
+ next_url = request.GET.get("next", "/chatbot/")
100
+ logger.info("Auto-logged in as 'testuser' because API auth is disabled. Redirecting.")
101
+ return redirect(next_url)
102
+ else:
103
+ logger.warning("Auto-login for 'testuser' failed (user/password incorrect or user doesn't exist).")
104
+ except Exception as auto_login_err:
105
+ logger.error(f"Error during 'testuser' auto-login attempt: {auto_login_err}")
106
+
107
+ # If authentication failed and auto-login didn't happen/failed
108
+ return render(request, "account/login.html", {"error": "Invalid username or password."})
109
+
110
+ # If GET request, just render the login form
111
+ return render(request, "account/login.html")
112
+
113
+ # Default config structure to return if the actual file is missing/invalid
114
+ DEFAULT_CONFIG = {
115
+ "llm": {
116
+ "default": {
117
+ "provider": "openai",
118
+ "model": "gpt-4o", # More modern default
119
+ "base_url": "https://api.openai.com/v1", # Standard OpenAI endpoint
120
+ "api_key": "", # API key should usually come from env vars
121
+ "temperature": 0.7
122
+ }
123
+ },
124
+ "mcpServers": {},
125
+ "blueprints": {}
126
+ }
127
+
128
+ @csrf_exempt # Usually not needed for GET, but doesn't hurt
129
+ def serve_swarm_config(request):
130
+ """Serve the main swarm configuration file (swarm_config.json) as JSON."""
131
+ # Construct path relative to Django settings.BASE_DIR
132
+ config_path = Path(settings.BASE_DIR) / "swarm_config.json"
133
+ logger.debug(f"Attempting to serve swarm config from: {config_path}")
134
+ try:
135
+ # Use Path object's read_text method for cleaner file reading
136
+ config_content = config_path.read_text(encoding='utf-8')
137
+ config_data = json.loads(config_content)
138
+ logger.debug("Successfully loaded and parsed swarm_config.json")
139
+ return JsonResponse(config_data)
140
+ except FileNotFoundError:
141
+ logger.error(f"Configuration file swarm_config.json not found at {config_path}. Serving default config.")
142
+ return JsonResponse(DEFAULT_CONFIG, status=404) # Return 404 maybe? Or just default?
143
+ except json.JSONDecodeError as e:
144
+ logger.error(f"Error decoding JSON from {config_path}: {e}")
145
+ # Return an error response instead of default config on parse error
146
+ return JsonResponse({"error": f"Invalid JSON format in configuration file: {e}"}, status=500)
147
+ except Exception as e:
148
+ logger.error(f"Unexpected error serving swarm config: {e}", exc_info=True)
149
+ return JsonResponse({"error": "An unexpected error occurred."}, status=500)
swarm/wsgi.py ADDED
@@ -0,0 +1,16 @@
1
+ # src/swarm/wsgi.py
2
+
3
+ import os
4
+ from pathlib import Path
5
+ from dotenv import load_dotenv
6
+ from django.core.wsgi import get_wsgi_application
7
+
8
+ # Define the base directory
9
+ BASE_DIR = Path(__file__).resolve().parent.parent
10
+
11
+ # Load environment variables from .env file
12
+ load_dotenv(dotenv_path=BASE_DIR / '.env')
13
+
14
+ os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'swarm.settings')
15
+
16
+ application = get_wsgi_application()