open-swarm 0.1.1745274976__py3-none-any.whl → 0.1.1748636259__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.
- open_swarm-0.1.1748636259.dist-info/METADATA +188 -0
- open_swarm-0.1.1748636259.dist-info/RECORD +82 -0
- {open_swarm-0.1.1745274976.dist-info → open_swarm-0.1.1748636259.dist-info}/WHEEL +2 -1
- open_swarm-0.1.1748636259.dist-info/entry_points.txt +3 -0
- open_swarm-0.1.1748636259.dist-info/top_level.txt +1 -0
- swarm/agent/agent.py +49 -0
- swarm/auth.py +48 -113
- swarm/consumers.py +0 -19
- swarm/extensions/blueprint/__init__.py +16 -30
- swarm/{core → extensions/blueprint}/agent_utils.py +1 -1
- swarm/extensions/blueprint/blueprint_base.py +458 -0
- swarm/extensions/blueprint/blueprint_discovery.py +112 -0
- swarm/extensions/blueprint/output_utils.py +95 -0
- swarm/{core → extensions/blueprint}/spinner.py +21 -30
- swarm/extensions/cli/cli_args.py +0 -6
- swarm/extensions/cli/commands/blueprint_management.py +9 -47
- swarm/extensions/cli/commands/config_management.py +6 -5
- swarm/extensions/cli/commands/edit_config.py +7 -16
- swarm/extensions/cli/commands/list_blueprints.py +1 -1
- swarm/extensions/cli/commands/validate_env.py +4 -11
- swarm/extensions/cli/commands/validate_envvars.py +6 -6
- swarm/extensions/cli/interactive_shell.py +2 -16
- swarm/extensions/config/config_loader.py +201 -107
- swarm/{core → extensions/config}/config_manager.py +38 -50
- swarm/{core → extensions/config}/server_config.py +0 -32
- swarm/extensions/launchers/build_launchers.py +14 -0
- swarm/{core → extensions/launchers}/build_swarm_wrapper.py +0 -0
- swarm/extensions/launchers/swarm_api.py +64 -8
- swarm/extensions/launchers/swarm_cli.py +300 -8
- swarm/llm/chat_completion.py +195 -0
- swarm/serializers.py +5 -96
- swarm/settings.py +111 -99
- swarm/urls.py +74 -57
- swarm/utils/context_utils.py +4 -10
- swarm/utils/general_utils.py +0 -21
- swarm/utils/redact.py +36 -23
- swarm/views/api_views.py +39 -48
- swarm/views/chat_views.py +70 -237
- swarm/views/core_views.py +87 -80
- swarm/views/model_views.py +121 -64
- swarm/views/utils.py +441 -65
- swarm/views/web_views.py +2 -2
- open_swarm-0.1.1745274976.dist-info/METADATA +0 -874
- open_swarm-0.1.1745274976.dist-info/RECORD +0 -318
- open_swarm-0.1.1745274976.dist-info/entry_points.txt +0 -4
- swarm/blueprints/README.md +0 -68
- swarm/blueprints/blueprint_audit_status.json +0 -27
- swarm/blueprints/chatbot/README.md +0 -40
- swarm/blueprints/chatbot/blueprint_chatbot.py +0 -471
- swarm/blueprints/chatbot/metadata.json +0 -23
- swarm/blueprints/chatbot/templates/chatbot/chatbot.html +0 -33
- swarm/blueprints/chucks_angels/README.md +0 -11
- swarm/blueprints/chucks_angels/blueprint_chucks_angels.py +0 -7
- swarm/blueprints/chucks_angels/test_basic.py +0 -3
- swarm/blueprints/codey/CODEY.md +0 -15
- swarm/blueprints/codey/README.md +0 -115
- swarm/blueprints/codey/blueprint_codey.py +0 -1072
- swarm/blueprints/codey/codey_cli.py +0 -373
- swarm/blueprints/codey/instructions.md +0 -17
- swarm/blueprints/codey/metadata.json +0 -23
- swarm/blueprints/common/operation_box_utils.py +0 -83
- swarm/blueprints/digitalbutlers/README.md +0 -11
- swarm/blueprints/digitalbutlers/__init__.py +0 -1
- swarm/blueprints/digitalbutlers/blueprint_digitalbutlers.py +0 -7
- swarm/blueprints/digitalbutlers/test_basic.py +0 -3
- swarm/blueprints/divine_code/README.md +0 -3
- swarm/blueprints/divine_code/__init__.py +0 -10
- swarm/blueprints/divine_code/apps.py +0 -11
- swarm/blueprints/divine_code/blueprint_divine_code.py +0 -270
- swarm/blueprints/django_chat/apps.py +0 -6
- swarm/blueprints/django_chat/blueprint_django_chat.py +0 -268
- swarm/blueprints/django_chat/templates/django_chat/django_chat_webpage.html +0 -37
- swarm/blueprints/django_chat/urls.py +0 -8
- swarm/blueprints/django_chat/views.py +0 -32
- swarm/blueprints/echocraft/blueprint_echocraft.py +0 -384
- swarm/blueprints/flock/README.md +0 -11
- swarm/blueprints/flock/__init__.py +0 -8
- swarm/blueprints/flock/blueprint_flock.py +0 -7
- swarm/blueprints/flock/test_basic.py +0 -3
- swarm/blueprints/geese/README.md +0 -97
- swarm/blueprints/geese/blueprint_geese.py +0 -803
- swarm/blueprints/geese/geese_cli.py +0 -102
- swarm/blueprints/jeeves/README.md +0 -41
- swarm/blueprints/jeeves/blueprint_jeeves.py +0 -722
- swarm/blueprints/jeeves/jeeves_cli.py +0 -55
- swarm/blueprints/jeeves/metadata.json +0 -24
- swarm/blueprints/mcp_demo/blueprint_mcp_demo.py +0 -473
- swarm/blueprints/messenger/templates/messenger/messenger.html +0 -46
- swarm/blueprints/mission_improbable/blueprint_mission_improbable.py +0 -423
- swarm/blueprints/monkai_magic/blueprint_monkai_magic.py +0 -340
- swarm/blueprints/nebula_shellz/blueprint_nebula_shellz.py +0 -265
- swarm/blueprints/omniplex/blueprint_omniplex.py +0 -298
- swarm/blueprints/poets/blueprint_poets.py +0 -546
- swarm/blueprints/poets/poets_cli.py +0 -23
- swarm/blueprints/rue_code/README.md +0 -8
- swarm/blueprints/rue_code/blueprint_rue_code.py +0 -448
- swarm/blueprints/rue_code/rue_code_cli.py +0 -43
- swarm/blueprints/stewie/apps.py +0 -12
- swarm/blueprints/stewie/blueprint_family_ties.py +0 -349
- swarm/blueprints/stewie/models.py +0 -19
- swarm/blueprints/stewie/serializers.py +0 -10
- swarm/blueprints/stewie/settings.py +0 -17
- swarm/blueprints/stewie/urls.py +0 -11
- swarm/blueprints/stewie/views.py +0 -26
- swarm/blueprints/suggestion/blueprint_suggestion.py +0 -222
- swarm/blueprints/whinge_surf/README.md +0 -22
- swarm/blueprints/whinge_surf/__init__.py +0 -1
- swarm/blueprints/whinge_surf/blueprint_whinge_surf.py +0 -565
- swarm/blueprints/whinge_surf/whinge_surf_cli.py +0 -99
- swarm/blueprints/whiskeytango_foxtrot/__init__.py +0 -0
- swarm/blueprints/whiskeytango_foxtrot/apps.py +0 -11
- swarm/blueprints/whiskeytango_foxtrot/blueprint_whiskeytango_foxtrot.py +0 -339
- swarm/blueprints/zeus/__init__.py +0 -2
- swarm/blueprints/zeus/apps.py +0 -4
- swarm/blueprints/zeus/blueprint_zeus.py +0 -270
- swarm/blueprints/zeus/zeus_cli.py +0 -13
- swarm/cli/async_input.py +0 -65
- swarm/cli/async_input_demo.py +0 -32
- swarm/core/blueprint_base.py +0 -769
- swarm/core/blueprint_discovery.py +0 -125
- swarm/core/blueprint_runner.py +0 -59
- swarm/core/blueprint_ux.py +0 -109
- swarm/core/build_launchers.py +0 -15
- swarm/core/cli/__init__.py +0 -1
- swarm/core/cli/commands/__init__.py +0 -1
- swarm/core/cli/commands/blueprint_management.py +0 -7
- swarm/core/cli/interactive_shell.py +0 -14
- swarm/core/cli/main.py +0 -50
- swarm/core/cli/utils/__init__.py +0 -1
- swarm/core/cli/utils/discover_commands.py +0 -18
- swarm/core/config_loader.py +0 -122
- swarm/core/output_utils.py +0 -193
- swarm/core/session_logger.py +0 -42
- swarm/core/slash_commands.py +0 -89
- swarm/core/swarm_api.py +0 -68
- swarm/core/swarm_cli.py +0 -216
- swarm/core/utils/__init__.py +0 -0
- swarm/extensions/blueprint/cli_handler.py +0 -197
- swarm/extensions/blueprint/runnable_blueprint.py +0 -42
- swarm/extensions/cli/utils/__init__.py +0 -1
- swarm/extensions/cli/utils/async_input.py +0 -46
- swarm/extensions/cli/utils/prompt_user.py +0 -3
- swarm/management/__init__.py +0 -0
- swarm/management/commands/__init__.py +0 -0
- swarm/management/commands/runserver.py +0 -58
- swarm/middleware.py +0 -65
- swarm/permissions.py +0 -38
- swarm/static/contrib/fonts/fontawesome-webfont.ttf +0 -7
- swarm/static/contrib/fonts/fontawesome-webfont.woff +0 -7
- swarm/static/contrib/fonts/fontawesome-webfont.woff2 +0 -7
- swarm/static/contrib/markedjs/marked.min.js +0 -6
- swarm/static/contrib/tabler-icons/adjustments-horizontal.svg +0 -27
- swarm/static/contrib/tabler-icons/alert-triangle.svg +0 -21
- swarm/static/contrib/tabler-icons/archive.svg +0 -21
- swarm/static/contrib/tabler-icons/artboard.svg +0 -27
- swarm/static/contrib/tabler-icons/automatic-gearbox.svg +0 -23
- swarm/static/contrib/tabler-icons/box-multiple.svg +0 -19
- swarm/static/contrib/tabler-icons/carambola.svg +0 -19
- swarm/static/contrib/tabler-icons/copy.svg +0 -20
- swarm/static/contrib/tabler-icons/download.svg +0 -21
- swarm/static/contrib/tabler-icons/edit.svg +0 -21
- swarm/static/contrib/tabler-icons/filled/carambola.svg +0 -13
- swarm/static/contrib/tabler-icons/filled/paint.svg +0 -13
- swarm/static/contrib/tabler-icons/headset.svg +0 -22
- swarm/static/contrib/tabler-icons/layout-sidebar-left-collapse.svg +0 -21
- swarm/static/contrib/tabler-icons/layout-sidebar-left-expand.svg +0 -21
- swarm/static/contrib/tabler-icons/layout-sidebar-right-collapse.svg +0 -21
- swarm/static/contrib/tabler-icons/layout-sidebar-right-expand.svg +0 -21
- swarm/static/contrib/tabler-icons/message-chatbot.svg +0 -22
- swarm/static/contrib/tabler-icons/message-star.svg +0 -22
- swarm/static/contrib/tabler-icons/message-x.svg +0 -23
- swarm/static/contrib/tabler-icons/message.svg +0 -21
- swarm/static/contrib/tabler-icons/paperclip.svg +0 -18
- swarm/static/contrib/tabler-icons/playlist-add.svg +0 -22
- swarm/static/contrib/tabler-icons/robot.svg +0 -26
- swarm/static/contrib/tabler-icons/search.svg +0 -19
- swarm/static/contrib/tabler-icons/settings.svg +0 -20
- swarm/static/contrib/tabler-icons/thumb-down.svg +0 -19
- swarm/static/contrib/tabler-icons/thumb-up.svg +0 -19
- swarm/static/css/dropdown.css +0 -22
- swarm/static/htmx/htmx.min.js +0 -0
- swarm/static/js/dropdown.js +0 -23
- swarm/static/rest_mode/css/base.css +0 -470
- swarm/static/rest_mode/css/chat-history.css +0 -286
- swarm/static/rest_mode/css/chat.css +0 -251
- swarm/static/rest_mode/css/chatbot.css +0 -74
- swarm/static/rest_mode/css/chatgpt.css +0 -62
- swarm/static/rest_mode/css/colors/corporate.css +0 -74
- swarm/static/rest_mode/css/colors/pastel.css +0 -81
- swarm/static/rest_mode/css/colors/tropical.css +0 -82
- swarm/static/rest_mode/css/general.css +0 -142
- swarm/static/rest_mode/css/layout.css +0 -167
- swarm/static/rest_mode/css/layouts/messenger-layout.css +0 -17
- swarm/static/rest_mode/css/layouts/minimalist-layout.css +0 -57
- swarm/static/rest_mode/css/layouts/mobile-layout.css +0 -8
- swarm/static/rest_mode/css/messages.css +0 -84
- swarm/static/rest_mode/css/messenger.css +0 -135
- swarm/static/rest_mode/css/settings.css +0 -91
- swarm/static/rest_mode/css/simple.css +0 -44
- swarm/static/rest_mode/css/slack.css +0 -58
- swarm/static/rest_mode/css/style.css +0 -156
- swarm/static/rest_mode/css/theme.css +0 -30
- swarm/static/rest_mode/css/toast.css +0 -40
- swarm/static/rest_mode/js/auth.js +0 -9
- swarm/static/rest_mode/js/blueprint.js +0 -41
- swarm/static/rest_mode/js/blueprintUtils.js +0 -12
- swarm/static/rest_mode/js/chatLogic.js +0 -79
- swarm/static/rest_mode/js/debug.js +0 -63
- swarm/static/rest_mode/js/events.js +0 -98
- swarm/static/rest_mode/js/main.js +0 -19
- swarm/static/rest_mode/js/messages.js +0 -264
- swarm/static/rest_mode/js/messengerLogic.js +0 -355
- swarm/static/rest_mode/js/modules/apiService.js +0 -84
- swarm/static/rest_mode/js/modules/blueprintManager.js +0 -162
- swarm/static/rest_mode/js/modules/chatHistory.js +0 -110
- swarm/static/rest_mode/js/modules/debugLogger.js +0 -14
- swarm/static/rest_mode/js/modules/eventHandlers.js +0 -107
- swarm/static/rest_mode/js/modules/messageProcessor.js +0 -120
- swarm/static/rest_mode/js/modules/state.js +0 -7
- swarm/static/rest_mode/js/modules/userInteractions.js +0 -29
- swarm/static/rest_mode/js/modules/validation.js +0 -23
- swarm/static/rest_mode/js/rendering.js +0 -119
- swarm/static/rest_mode/js/settings.js +0 -130
- swarm/static/rest_mode/js/sidebar.js +0 -94
- swarm/static/rest_mode/js/simpleLogic.js +0 -37
- swarm/static/rest_mode/js/slackLogic.js +0 -66
- swarm/static/rest_mode/js/splash.js +0 -76
- swarm/static/rest_mode/js/theme.js +0 -111
- swarm/static/rest_mode/js/toast.js +0 -36
- swarm/static/rest_mode/js/ui.js +0 -265
- swarm/static/rest_mode/js/validation.js +0 -57
- swarm/static/rest_mode/svg/animated_spinner.svg +0 -12
- swarm/static/rest_mode/svg/arrow_down.svg +0 -5
- swarm/static/rest_mode/svg/arrow_left.svg +0 -5
- swarm/static/rest_mode/svg/arrow_right.svg +0 -5
- swarm/static/rest_mode/svg/arrow_up.svg +0 -5
- swarm/static/rest_mode/svg/attach.svg +0 -8
- swarm/static/rest_mode/svg/avatar.svg +0 -7
- swarm/static/rest_mode/svg/canvas.svg +0 -6
- swarm/static/rest_mode/svg/chat_history.svg +0 -4
- swarm/static/rest_mode/svg/close.svg +0 -5
- swarm/static/rest_mode/svg/copy.svg +0 -4
- swarm/static/rest_mode/svg/dark_mode.svg +0 -3
- swarm/static/rest_mode/svg/edit.svg +0 -5
- swarm/static/rest_mode/svg/layout.svg +0 -9
- swarm/static/rest_mode/svg/logo.svg +0 -29
- swarm/static/rest_mode/svg/logout.svg +0 -5
- swarm/static/rest_mode/svg/mobile.svg +0 -5
- swarm/static/rest_mode/svg/new_chat.svg +0 -4
- swarm/static/rest_mode/svg/not_visible.svg +0 -5
- swarm/static/rest_mode/svg/plus.svg +0 -7
- swarm/static/rest_mode/svg/run_code.svg +0 -6
- swarm/static/rest_mode/svg/save.svg +0 -4
- swarm/static/rest_mode/svg/search.svg +0 -6
- swarm/static/rest_mode/svg/settings.svg +0 -4
- swarm/static/rest_mode/svg/speaker.svg +0 -5
- swarm/static/rest_mode/svg/stop.svg +0 -6
- swarm/static/rest_mode/svg/thumbs_down.svg +0 -3
- swarm/static/rest_mode/svg/thumbs_up.svg +0 -3
- swarm/static/rest_mode/svg/toggle_off.svg +0 -6
- swarm/static/rest_mode/svg/toggle_on.svg +0 -6
- swarm/static/rest_mode/svg/trash.svg +0 -10
- swarm/static/rest_mode/svg/undo.svg +0 -3
- swarm/static/rest_mode/svg/visible.svg +0 -8
- swarm/static/rest_mode/svg/voice.svg +0 -10
- swarm/templates/account/login.html +0 -22
- swarm/templates/account/signup.html +0 -32
- swarm/templates/base.html +0 -30
- swarm/templates/chat.html +0 -43
- swarm/templates/index.html +0 -35
- swarm/templates/rest_mode/components/chat_sidebar.html +0 -55
- swarm/templates/rest_mode/components/header.html +0 -45
- swarm/templates/rest_mode/components/main_chat_pane.html +0 -41
- swarm/templates/rest_mode/components/settings_dialog.html +0 -97
- swarm/templates/rest_mode/components/splash_screen.html +0 -7
- swarm/templates/rest_mode/components/top_bar.html +0 -28
- swarm/templates/rest_mode/message_ui.html +0 -50
- swarm/templates/rest_mode/slackbot.html +0 -30
- swarm/templates/simple_blueprint_page.html +0 -24
- swarm/templates/websocket_partials/final_system_message.html +0 -3
- swarm/templates/websocket_partials/system_message.html +0 -4
- swarm/templates/websocket_partials/user_message.html +0 -5
- swarm/utils/ansi_box.py +0 -34
- swarm/utils/disable_tracing.py +0 -38
- swarm/utils/log_utils.py +0 -63
- swarm/utils/openai_patch.py +0 -33
- swarm/ux/ansi_box.py +0 -43
- swarm/ux/spinner.py +0 -53
- {open_swarm-0.1.1745274976.dist-info → open_swarm-0.1.1748636259.dist-info}/licenses/LICENSE +0 -0
- /swarm/{core → extensions/blueprint}/blueprint_utils.py +0 -0
- /swarm/{core → extensions/blueprint}/common_utils.py +0 -0
- /swarm/{core → extensions/config}/setup_wizard.py +0 -0
- /swarm/{blueprints/rue_code → extensions/config/utils}/__init__.py +0 -0
- /swarm/{core → extensions/config}/utils/logger.py +0 -0
- /swarm/{core → extensions/launchers}/swarm_wrapper.py +0 -0
swarm/views/core_views.py
CHANGED
@@ -11,101 +11,108 @@ from django.http import JsonResponse, HttpResponse
|
|
11
11
|
from django.conf import settings
|
12
12
|
from django.views.decorators.csrf import csrf_exempt
|
13
13
|
from django.contrib.auth import authenticate, login
|
14
|
-
from django.contrib.auth.forms import AuthenticationForm # Use standard auth form
|
15
|
-
|
16
14
|
|
17
15
|
# Assuming blueprint discovery happens elsewhere and results are available if needed
|
18
16
|
# from .utils import blueprints_metadata # Or however metadata is accessed
|
19
|
-
|
20
|
-
# Use the current config loader
|
21
|
-
from swarm.core import config_loader, server_config
|
17
|
+
from swarm.extensions.config.config_loader import load_server_config # Import if needed
|
22
18
|
|
23
19
|
logger = logging.getLogger(__name__)
|
24
20
|
|
25
|
-
#
|
21
|
+
# Placeholder for blueprint metadata if needed by index
|
22
|
+
# In a real app, this might be loaded dynamically or passed via context
|
23
|
+
try:
|
24
|
+
# Attempt to import the discovery function if views need dynamic data
|
25
|
+
from swarm.extensions.blueprint.blueprint_discovery import discover_blueprints
|
26
|
+
# Note: Calling discover_blueprints here might be too early or cause issues.
|
27
|
+
# It's often better handled in specific views that need it (like list_models)
|
28
|
+
# or passed via Django context processors.
|
29
|
+
# For now, provide an empty dict as fallback.
|
30
|
+
try:
|
31
|
+
# Use settings.BLUEPRINTS_DIR which should be configured
|
32
|
+
blueprints_metadata = discover_blueprints(directories=[str(settings.BLUEPRINTS_DIR)])
|
33
|
+
except Exception:
|
34
|
+
blueprints_metadata = {}
|
35
|
+
except ImportError:
|
36
|
+
blueprints_metadata = {}
|
37
|
+
|
26
38
|
|
39
|
+
@csrf_exempt
|
27
40
|
def index(request):
|
28
|
-
"""Render the main index page
|
29
|
-
|
30
|
-
#
|
31
|
-
|
41
|
+
"""Render the main index page with blueprint options."""
|
42
|
+
logger.debug("Rendering index page")
|
43
|
+
# Get blueprint names from the potentially loaded metadata
|
44
|
+
blueprint_names_list = list(blueprints_metadata.keys())
|
32
45
|
context = {
|
33
|
-
|
34
|
-
|
35
|
-
|
46
|
+
"dark_mode": request.session.get('dark_mode', True),
|
47
|
+
"enable_admin": os.getenv("ENABLE_ADMIN", "false").lower() in ("true", "1", "t"),
|
48
|
+
"blueprints": blueprint_names_list # Pass the list of names
|
36
49
|
}
|
37
|
-
|
38
|
-
template_name = "swarm/index.html"
|
39
|
-
# Check if template exists? Django handles TemplateDoesNotExist.
|
40
|
-
return render(request, template_name, context)
|
41
|
-
|
42
|
-
def custom_login(request):
|
43
|
-
"""Handles user login."""
|
44
|
-
if request.method == 'POST':
|
45
|
-
form = AuthenticationForm(request, data=request.POST)
|
46
|
-
if form.is_valid():
|
47
|
-
username = form.cleaned_data.get('username')
|
48
|
-
password = form.cleaned_data.get('password')
|
49
|
-
user = authenticate(username=username, password=password)
|
50
|
-
if user is not None:
|
51
|
-
login(request, user)
|
52
|
-
logger.info(f"User '{username}' logged in successfully.")
|
53
|
-
return redirect('/') # Redirect to index after login
|
54
|
-
else:
|
55
|
-
logger.warning(f"Login failed for user '{username}': Invalid credentials.")
|
56
|
-
# Return form with error (AuthenticationForm handles this)
|
57
|
-
else:
|
58
|
-
logger.warning(f"Login form invalid: {form.errors.as_json()}")
|
59
|
-
else:
|
60
|
-
form = AuthenticationForm()
|
61
|
-
|
62
|
-
# Only render if ENABLE_WEBUI is true (checked in urls.py)
|
63
|
-
return render(request, 'swarm/login.html', {'form': form})
|
50
|
+
return render(request, "index.html", context)
|
64
51
|
|
52
|
+
DEFAULT_CONFIG = {
|
53
|
+
"llm": {
|
54
|
+
"default": {
|
55
|
+
"provider": "openai",
|
56
|
+
"model": "gpt-4o", # Example fallback model
|
57
|
+
"base_url": "https://api.openai.com/v1",
|
58
|
+
"api_key": "",
|
59
|
+
"temperature": 0.3
|
60
|
+
}
|
61
|
+
},
|
62
|
+
"blueprints": {},
|
63
|
+
"mcpServers": {}
|
64
|
+
}
|
65
65
|
|
66
66
|
def serve_swarm_config(request):
|
67
|
-
"""
|
68
|
-
# Find the config file used by the blueprint base or config loader
|
69
|
-
# This logic might need refinement depending on where config is reliably found
|
70
|
-
config_path = None
|
67
|
+
"""Serve the swarm configuration file as JSON."""
|
71
68
|
try:
|
72
|
-
|
73
|
-
|
74
|
-
|
75
|
-
|
76
|
-
|
77
|
-
|
69
|
+
# Use load_server_config which handles finding the file
|
70
|
+
config_data = load_server_config()
|
71
|
+
return JsonResponse(config_data)
|
72
|
+
except (FileNotFoundError, ValueError, Exception) as e:
|
73
|
+
logger.error(f"Error serving swarm_config.json: {e}. Serving default.")
|
74
|
+
# Return a default config on error
|
75
|
+
return JsonResponse(DEFAULT_CONFIG, status=500)
|
76
|
+
|
78
77
|
|
79
|
-
|
80
|
-
|
81
|
-
|
82
|
-
|
83
|
-
|
84
|
-
|
85
|
-
|
86
|
-
|
87
|
-
|
88
|
-
|
89
|
-
|
78
|
+
@csrf_exempt
|
79
|
+
def custom_login(request):
|
80
|
+
"""Handle custom login at /accounts/login/, redirecting to 'next' URL on success."""
|
81
|
+
from django.contrib.auth.models import User # Import here to avoid potential early init issues
|
82
|
+
if request.method == "POST":
|
83
|
+
username = request.POST.get("username")
|
84
|
+
password = request.POST.get("password")
|
85
|
+
user = authenticate(request, username=username, password=password)
|
86
|
+
if user is not None:
|
87
|
+
login(request, user)
|
88
|
+
next_url = request.GET.get("next", getattr(settings, 'LOGIN_REDIRECT_URL', '/')) # Use setting or fallback
|
89
|
+
logger.info(f"User '{username}' logged in successfully. Redirecting to {next_url}")
|
90
|
+
return redirect(next_url)
|
91
|
+
else:
|
92
|
+
# If ENABLE_API_AUTH is false, auto-login as testuser (for dev/test convenience)
|
93
|
+
enable_auth = os.getenv("ENABLE_API_AUTH", "true").lower() in ("true", "1", "t") # Default to TRUE
|
94
|
+
if not enable_auth:
|
95
|
+
try:
|
96
|
+
# Ensure test user exists and has a known password
|
97
|
+
user, created = User.objects.get_or_create(username="testuser")
|
98
|
+
if created or not user.has_usable_password():
|
99
|
+
user.set_password("testpass") # Set a default password
|
100
|
+
user.save()
|
90
101
|
|
91
|
-
|
92
|
-
|
93
|
-
|
102
|
+
if user.check_password("testpass"): # Check against the known password
|
103
|
+
login(request, user)
|
104
|
+
next_url = request.GET.get("next", getattr(settings, 'LOGIN_REDIRECT_URL', '/'))
|
105
|
+
logger.info(f"Auto-logged in as 'testuser' since ENABLE_API_AUTH is false")
|
106
|
+
return redirect(next_url)
|
107
|
+
else:
|
108
|
+
logger.warning("Auto-login failed: 'testuser' exists but password incorrect.")
|
94
109
|
|
95
|
-
|
96
|
-
|
110
|
+
except Exception as auto_login_err:
|
111
|
+
logger.error(f"Error during testuser auto-login attempt: {auto_login_err}")
|
112
|
+
# If authentication failed (and auto-login didn't happen or failed)
|
113
|
+
logger.warning(f"Login failed for user '{username}'.")
|
114
|
+
return render(request, "account/login.html", {"error": "Invalid credentials"})
|
115
|
+
# If GET request
|
116
|
+
return render(request, "account/login.html")
|
97
117
|
|
98
|
-
|
99
|
-
def list_available_blueprints_api(request):
|
100
|
-
"""API endpoint to list discoverable blueprints."""
|
101
|
-
# Re-use discovery logic if possible, or adapt from CLI
|
102
|
-
from swarm.extensions.blueprint.discovery import discover_blueprints # Assuming this exists
|
103
|
-
try:
|
104
|
-
bp_dir = Path(settings.BLUEPRINTS_DIR) # Assuming settings has BLUEPRINTS_DIR
|
105
|
-
discovered = discover_blueprints(directories=[str(bp_dir)])
|
106
|
-
# Format the response
|
107
|
-
blueprint_list = [{"name": name, "description": meta.get("description", "N/A")} for name, meta in discovered.items()]
|
108
|
-
return JsonResponse({"blueprints": blueprint_list})
|
109
|
-
except Exception as e:
|
110
|
-
logger.error(f"Error listing blueprints via API: {e}", exc_info=True)
|
111
|
-
return JsonResponse({"error": "Failed to list blueprints."}, status=500)
|
118
|
+
# Add any other views that were originally in the main views.py if needed
|
swarm/views/model_views.py
CHANGED
@@ -1,78 +1,135 @@
|
|
1
1
|
"""
|
2
|
-
|
2
|
+
Model listing views for Open Swarm MCP Core.
|
3
|
+
Dynamically discovers blueprints and lists them alongside configured LLMs.
|
3
4
|
"""
|
4
|
-
import
|
5
|
-
from django.
|
6
|
-
from
|
7
|
-
from
|
8
|
-
from django.views.decorators.csrf import csrf_exempt
|
9
|
-
|
10
|
-
from rest_framework.views import APIView
|
11
|
-
from rest_framework.response import Response
|
12
|
-
from rest_framework.permissions import AllowAny, IsAuthenticated
|
13
|
-
from rest_framework import status
|
14
|
-
|
5
|
+
import os
|
6
|
+
from django.http import JsonResponse
|
7
|
+
from rest_framework.decorators import api_view, permission_classes, authentication_classes
|
8
|
+
from rest_framework.permissions import AllowAny # Import AllowAny
|
15
9
|
from drf_spectacular.utils import extend_schema
|
16
10
|
|
17
|
-
|
18
|
-
|
11
|
+
from swarm.utils.logger_setup import setup_logger
|
12
|
+
# Import the function to discover blueprints, not the metadata variable
|
13
|
+
from swarm.extensions.blueprint.blueprint_discovery import discover_blueprints
|
14
|
+
# Import utility to filter blueprints if needed
|
15
|
+
from swarm.extensions.blueprint.blueprint_utils import filter_blueprints
|
16
|
+
# Import config loader or access config globally if set up
|
17
|
+
# Using utils seems less direct, let's assume config needs loading or is globally available
|
18
|
+
# from swarm.views.utils import config # This import might be problematic, load directly if needed
|
19
|
+
from swarm.extensions.config.config_loader import load_server_config
|
20
|
+
from swarm.settings import BLUEPRINTS_DIR # Import the directory setting
|
19
21
|
|
20
|
-
|
21
|
-
from .utils import get_available_blueprints
|
22
|
-
from ..permissions import HasValidTokenOrSession
|
22
|
+
logger = setup_logger(__name__)
|
23
23
|
|
24
|
-
|
24
|
+
@extend_schema(
|
25
|
+
responses={
|
26
|
+
200: {
|
27
|
+
"type": "object",
|
28
|
+
"properties": {
|
29
|
+
"object": {"type": "string"},
|
30
|
+
"data": {
|
31
|
+
"type": "array",
|
32
|
+
"items": {
|
33
|
+
"type": "object",
|
34
|
+
"properties": {
|
35
|
+
"id": {"type": "string"},
|
36
|
+
"object": {"type": "string"},
|
37
|
+
"title": {"type": "string"},
|
38
|
+
"description": {"type": "string"}
|
39
|
+
}
|
40
|
+
}
|
41
|
+
}
|
42
|
+
}
|
43
|
+
}
|
44
|
+
},
|
45
|
+
summary="Lists LLMs, config-defined blueprints, and discovered blueprints as models."
|
46
|
+
)
|
47
|
+
@api_view(["GET"])
|
48
|
+
@permission_classes([AllowAny]) # Use AllowAny directly
|
49
|
+
@authentication_classes([]) # No authentication required for listing models
|
50
|
+
def list_models(request):
|
51
|
+
"""List available LLMs, config-defined blueprints, and discovered blueprints."""
|
52
|
+
if request.method != "GET":
|
53
|
+
return JsonResponse({"error": "Method not allowed. Use GET."}, status=405)
|
25
54
|
|
26
|
-
|
27
|
-
#
|
28
|
-
#
|
55
|
+
try:
|
56
|
+
# Load configuration each time or ensure it's loaded globally/cached
|
57
|
+
config = load_server_config() # Load config to get LLMs and config blueprints
|
29
58
|
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
|
59
|
+
# 1. LLMs from config (marked as passthrough)
|
60
|
+
llm_config = config.get("llm", {})
|
61
|
+
llm_data = [
|
62
|
+
{
|
63
|
+
"id": key,
|
64
|
+
"object": "llm", # Mark as llm type
|
65
|
+
"title": conf.get("model", key), # Use model name or key as title
|
66
|
+
"description": f"Provider: {conf.get('provider', 'N/A')}, Model: {conf.get('model', 'N/A')}"
|
67
|
+
}
|
68
|
+
for key, conf in llm_config.items() if conf.get("passthrough")
|
69
|
+
]
|
36
70
|
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
|
42
|
-
|
43
|
-
|
44
|
-
|
45
|
-
|
46
|
-
|
71
|
+
# 2. Blueprints defined directly in swarm_config.json
|
72
|
+
config_blueprints = config.get("blueprints", {})
|
73
|
+
config_bp_data = [
|
74
|
+
{
|
75
|
+
"id": key,
|
76
|
+
"object": "blueprint", # Mark as blueprint type
|
77
|
+
"title": bp.get("title", key),
|
78
|
+
"description": bp.get("description", f"Blueprint '{key}' from configuration file.")
|
79
|
+
}
|
80
|
+
for key, bp in config_blueprints.items()
|
81
|
+
]
|
82
|
+
|
83
|
+
# 3. Dynamically discovered blueprints from the blueprints directory
|
84
|
+
# Ensure BLUEPRINTS_DIR is correctly pointing to your blueprints location relative to project root
|
47
85
|
try:
|
48
|
-
#
|
49
|
-
|
50
|
-
|
86
|
+
# Call discover_blueprints function to get the metadata dictionary
|
87
|
+
discovered_blueprints_metadata = discover_blueprints(directories=[BLUEPRINTS_DIR])
|
88
|
+
except FileNotFoundError:
|
89
|
+
logger.warning(f"Blueprints directory '{BLUEPRINTS_DIR}' not found. No blueprints discovered dynamically.")
|
90
|
+
discovered_blueprints_metadata = {}
|
91
|
+
except Exception as discover_err:
|
92
|
+
logger.error(f"Error discovering blueprints: {discover_err}", exc_info=True)
|
93
|
+
discovered_blueprints_metadata = {}
|
51
94
|
|
52
|
-
models_data = [
|
53
|
-
{
|
54
|
-
"id": model_id,
|
55
|
-
"object": "model",
|
56
|
-
"created": 0, # Placeholder
|
57
|
-
"owned_by": "open-swarm",
|
58
|
-
# Access metadata safely
|
59
|
-
"profile_name": metadata.get('profile_name', 'unknown') if isinstance(metadata, dict) else 'unknown'
|
60
|
-
}
|
61
|
-
# Ensure iteration works correctly
|
62
|
-
for model_id, metadata in (available_blueprints_dict.items() if isinstance(available_blueprints_dict, dict) else [])
|
63
|
-
]
|
64
95
|
|
65
|
-
|
66
|
-
|
67
|
-
|
96
|
+
# Filter discovered blueprints based on environment variable if set
|
97
|
+
allowed_blueprints_str = os.getenv("SWARM_BLUEPRINTS")
|
98
|
+
if allowed_blueprints_str and allowed_blueprints_str.strip():
|
99
|
+
# Use the imported filter_blueprints utility
|
100
|
+
final_discovered_metadata = filter_blueprints(discovered_blueprints_metadata, allowed_blueprints_str)
|
101
|
+
logger.info(f"Filtering discovered blueprints based on SWARM_BLUEPRINTS env var. Kept: {list(final_discovered_metadata.keys())}")
|
102
|
+
else:
|
103
|
+
final_discovered_metadata = discovered_blueprints_metadata # Use all discovered if no filter
|
104
|
+
|
105
|
+
# Format discovered blueprint data
|
106
|
+
discovered_bp_data = [
|
107
|
+
{
|
108
|
+
"id": key,
|
109
|
+
"object": "blueprint", # Mark as blueprint type
|
110
|
+
"title": meta.get("title", key),
|
111
|
+
"description": meta.get("description", f"Discovered blueprint '{key}'.")
|
68
112
|
}
|
69
|
-
|
70
|
-
|
113
|
+
for key, meta in final_discovered_metadata.items()
|
114
|
+
]
|
115
|
+
|
116
|
+
# 4. Merge all data sources
|
117
|
+
# Start with LLMs and config blueprints
|
118
|
+
merged_data = llm_data + config_bp_data
|
119
|
+
# Keep track of IDs already added
|
120
|
+
seen_ids = {item["id"] for item in merged_data}
|
121
|
+
# Add discovered blueprints only if their ID hasn't been used by config/LLMs
|
122
|
+
for bp_item in discovered_bp_data:
|
123
|
+
if bp_item["id"] not in seen_ids:
|
124
|
+
merged_data.append(bp_item)
|
125
|
+
seen_ids.add(bp_item["id"]) # Mark ID as seen
|
126
|
+
|
127
|
+
logger.debug(f"Returning {len(merged_data)} models (LLMs + Blueprints).")
|
128
|
+
# Return the merged list in the expected OpenAI-like format
|
129
|
+
return JsonResponse({"object": "list", "data": merged_data}, status=200)
|
130
|
+
|
131
|
+
except Exception as e:
|
132
|
+
# Catch-all for unexpected errors during the process
|
133
|
+
logger.error(f"Error listing models: {e}", exc_info=True)
|
134
|
+
return JsonResponse({"error": "Internal Server Error while listing models."}, status=500)
|
71
135
|
|
72
|
-
except Exception as e:
|
73
|
-
logger.error(f"Error retrieving available blueprints: {e}", exc_info=True)
|
74
|
-
# Return the standard sync Response
|
75
|
-
return Response(
|
76
|
-
{"error": "Internal server error retrieving models."},
|
77
|
-
status=status.HTTP_500_INTERNAL_SERVER_ERROR
|
78
|
-
)
|