open-swarm 0.1.1743371918__py3-none-any.whl → 0.1.1743416034__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.1743371918.dist-info → open_swarm-0.1.1743416034.dist-info}/METADATA +2 -2
- {open_swarm-0.1.1743371918.dist-info → open_swarm-0.1.1743416034.dist-info}/RECORD +8 -7
- {open_swarm-0.1.1743371918.dist-info → open_swarm-0.1.1743416034.dist-info}/entry_points.txt +1 -0
- swarm/blueprints/burnt_noodles/blueprint_burnt_noodles.py +4 -4
- swarm/middleware.py +65 -0
- swarm/settings.py +4 -0
- {open_swarm-0.1.1743371918.dist-info → open_swarm-0.1.1743416034.dist-info}/WHEEL +0 -0
- {open_swarm-0.1.1743371918.dist-info → open_swarm-0.1.1743416034.dist-info}/licenses/LICENSE +0 -0
@@ -1,6 +1,6 @@
|
|
1
1
|
Metadata-Version: 2.4
|
2
2
|
Name: open-swarm
|
3
|
-
Version: 0.1.
|
3
|
+
Version: 0.1.1743416034
|
4
4
|
Summary: Open Swarm: Orchestrating AI Agent Swarms with Django
|
5
5
|
Project-URL: Homepage, https://github.com/yourusername/open-swarm
|
6
6
|
Project-URL: Documentation, https://github.com/yourusername/open-swarm/blob/main/README.md
|
@@ -104,7 +104,7 @@ Open Swarm can be used in two primary ways:
|
|
104
104
|
|
105
105
|
* **Agents:** Individual AI units performing specific tasks, powered by LLMs (like GPT-4, Claude, etc.). Built using the `openai-agents` SDK.
|
106
106
|
* **Blueprints:** Python classes (`BlueprintBase` subclasses) defining a swarm's structure, agents, coordination logic, and external dependencies (like required environment variables or MCP servers). They act as reusable templates for specific tasks (e.g., code generation, research, data analysis).
|
107
|
-
* **MCP (
|
107
|
+
* **MCP (Model Context Protocol) Servers:** Optional external processes providing specialized capabilities (tools) to agents, such as filesystem access, web browsing, database interaction, or interacting with specific APIs (Slack, Monday.com, etc.). Agents interact with MCP servers via a standardized communication protocol.
|
108
108
|
* **Configuration (`swarm_config.json`):** A central JSON file defining available LLM profiles (API keys, models) and configurations for MCP servers. Typically managed via `swarm-cli` in `~/.config/swarm/`.
|
109
109
|
* **`swarm-cli`:** A command-line tool for managing blueprints (adding, listing, running, installing) and the `swarm_config.json` file. Uses XDG directories for storing blueprints (`~/.local/share/swarm/blueprints/`) and configuration (`~/.config/swarm/`).
|
110
110
|
* **`swarm-api`:** A launcher for the Django/DRF backend that exposes installed blueprints via an OpenAI-compatible REST API (`/v1/models`, `/v1/chat/completions`).
|
@@ -3,17 +3,18 @@ swarm/apps.py,sha256=up4C3m2JeyXeUcH-wYeReCuiOBVJ6404w9OfaRChLwM,2568
|
|
3
3
|
swarm/auth.py,sha256=8JIk1VbBvFFwOijEJAsrx6si802ZSMGnErXvmo0izUg,5935
|
4
4
|
swarm/consumers.py,sha256=wESLamkhbi4SEZt9k3yx6eU9ufOIZMCAL-OAXjJBGXE,5056
|
5
5
|
swarm/messages.py,sha256=CwADrjlj-uVmm-so1xIZvN1UkEWdzSn_hu7slfhuS8w,6549
|
6
|
+
swarm/middleware.py,sha256=lPlHbFg9Rm9lUuvg026d4zTDjRMc8bQi0JegpGdqIZQ,3198
|
6
7
|
swarm/models.py,sha256=Ix0WEYYqza2lbOEBNesikRCs3XGUPWmqQyMWzZYUaxM,1494
|
7
8
|
swarm/permissions.py,sha256=iM86fSL1TtgqJzgDkS3Dl82X6Xk7VDHWwdBDfs5RKWc,1671
|
8
9
|
swarm/serializers.py,sha256=4g3G2FdWpSIuLLC_SBKoNITw1b0G83Bxo7YHc-kjsro,4550
|
9
|
-
swarm/settings.py,sha256=
|
10
|
+
swarm/settings.py,sha256=wrQoWfNylY_54z5c54x0TLe2Q9KEqvawNXjqCVhWuyI,6616
|
10
11
|
swarm/tool_executor.py,sha256=KHM2mTGgbbTgWNN3fbV5c4MDY238OTLwaaqtkczFHFQ,12385
|
11
12
|
swarm/urls.py,sha256=9eRQWsB-Vs3Nmes4mtlZtk_Rvuixf4Y9uwrX9dVQ9Is,3292
|
12
13
|
swarm/util.py,sha256=G4x2hXopHhB7IdGCkUXGoykYWyiICnjxg7wcr-WqL8I,4644
|
13
14
|
swarm/wsgi.py,sha256=REM_u4HpMCkO0ddrOUXgtY-ITL-VTbRB1-WHvFJAtAU,408
|
14
15
|
swarm/agent/__init__.py,sha256=YESGu_UXEBxrlQwghodUMN0vmXZDwWMU7DclCUvoklA,104
|
15
16
|
swarm/blueprints/README.md,sha256=tsngbSB9N0tILcz_m1OGAjyKZQYlGTN-i5e5asq1GbE,8478
|
16
|
-
swarm/blueprints/burnt_noodles/blueprint_burnt_noodles.py,sha256=
|
17
|
+
swarm/blueprints/burnt_noodles/blueprint_burnt_noodles.py,sha256=MDwjlA4HQ6GFh7Z-XGM0Wdh0FzQdOHf38p3Y580EgWM,23008
|
17
18
|
swarm/blueprints/chatbot/blueprint_chatbot.py,sha256=D31OgSoxllhzn8f7cdVYflqzadN2SZ61rabPuK6EqQ8,4728
|
18
19
|
swarm/blueprints/chatbot/templates/chatbot/chatbot.html,sha256=REFnqNg0EHsXxAUfaCJe1YgOKiV_umBXuC6y8veF5CU,1568
|
19
20
|
swarm/blueprints/digitalbutlers/blueprint_digitalbutlers.py,sha256=JK_rmZgPMw4PdQFrMverrwgcjH0NRkuqkchYOJwXYuM,9809
|
@@ -253,8 +254,8 @@ swarm/views/message_views.py,sha256=sDUnXyqKXC8WwIIMAlWf00s2_a2T9c75Na5FvYMJwBM,
|
|
253
254
|
swarm/views/model_views.py,sha256=aAbU4AZmrOTaPeKMWtoKK7FPYHdaN3Zbx55JfKzYTRY,2937
|
254
255
|
swarm/views/utils.py,sha256=geX3Z5ZDKFYyXYBMilc-4qgOSjhujK3AfRtvbXgFpXk,3643
|
255
256
|
swarm/views/web_views.py,sha256=ExQQeJpZ8CkLZQC_pXKOOmdnEy2qR3wEBP4LLp27DPU,7404
|
256
|
-
open_swarm-0.1.
|
257
|
-
open_swarm-0.1.
|
258
|
-
open_swarm-0.1.
|
259
|
-
open_swarm-0.1.
|
260
|
-
open_swarm-0.1.
|
257
|
+
open_swarm-0.1.1743416034.dist-info/METADATA,sha256=rUCsvDnHgcapfgloeHA_QOGi2DbDGlxMKwHY5g_xPSM,13678
|
258
|
+
open_swarm-0.1.1743416034.dist-info/WHEEL,sha256=qtCwoSJWgHk21S1Kb4ihdzI2rlJ1ZKaIurTj_ngOhyQ,87
|
259
|
+
open_swarm-0.1.1743416034.dist-info/entry_points.txt,sha256=z1UIVRRhri-V-hWxFkDEYu0SZPUIsVO4KpDaodgcFzU,125
|
260
|
+
open_swarm-0.1.1743416034.dist-info/licenses/LICENSE,sha256=BU9bwRlnOt_JDIb6OT55Q4leLZx9RArDLTFnlDIrBEI,1062
|
261
|
+
open_swarm-0.1.1743416034.dist-info/RECORD,,
|
@@ -56,7 +56,6 @@ def git_status() -> str:
|
|
56
56
|
except Exception as e:
|
57
57
|
logger.error(f"Unexpected error during git status: {e}", exc_info=logger.level <= logging.DEBUG)
|
58
58
|
return f"Error during git status: {e}"
|
59
|
-
|
60
59
|
@function_tool
|
61
60
|
def git_diff() -> str:
|
62
61
|
"""Executes 'git diff' and returns the differences in the working directory."""
|
@@ -286,7 +285,7 @@ class BurntNoodlesBlueprint(BlueprintBase):
|
|
286
285
|
|
287
286
|
logger.debug(f"Creating new Model instance for profile '{profile_name}'.")
|
288
287
|
# Retrieve profile data using BlueprintBase helper method
|
289
|
-
profile_data = self
|
288
|
+
profile_data = getattr(self, "get_llm_profile", lambda prof: {"provider": "openai", "model": "gpt-mock"})(profile_name)
|
290
289
|
if not profile_data:
|
291
290
|
# Critical error if the profile (or default fallback) isn't found
|
292
291
|
logger.critical(f"Cannot create Model instance: LLM profile '{profile_name}' (or 'default') not found in configuration.")
|
@@ -341,12 +340,13 @@ class BurntNoodlesBlueprint(BlueprintBase):
|
|
341
340
|
The starting agent instance (Michael Toasted).
|
342
341
|
"""
|
343
342
|
logger.debug("Creating Burnt Noodles agent team...")
|
343
|
+
config = self._load_configuration() if getattr(self, "config", None) is None else self.config
|
344
344
|
# Clear caches at the start of agent creation for this run
|
345
345
|
self._model_instance_cache = {}
|
346
346
|
self._openai_client_cache = {}
|
347
|
-
|
347
|
+
|
348
348
|
# Determine the LLM profile to use (e.g., from config or default)
|
349
|
-
default_profile_name =
|
349
|
+
default_profile_name = config.get("llm_profile", "default")
|
350
350
|
logger.debug(f"Using LLM profile '{default_profile_name}' for all Burnt Noodles agents.")
|
351
351
|
# Get the single Model instance to share among agents (or create if needed)
|
352
352
|
default_model_instance = self._get_model_instance(default_profile_name)
|
swarm/middleware.py
ADDED
@@ -0,0 +1,65 @@
|
|
1
|
+
# src/swarm/middleware.py
|
2
|
+
import logging
|
3
|
+
import asyncio # Import asyncio
|
4
|
+
from asgiref.sync import sync_to_async
|
5
|
+
from django.utils.functional import SimpleLazyObject
|
6
|
+
from django.utils.decorators import sync_and_async_middleware
|
7
|
+
from django.contrib.auth.middleware import AuthenticationMiddleware
|
8
|
+
|
9
|
+
logger = logging.getLogger(__name__)
|
10
|
+
|
11
|
+
# Mark the middleware as compatible with both sync and async views
|
12
|
+
@sync_and_async_middleware
|
13
|
+
def AsyncAuthMiddleware(get_response):
|
14
|
+
"""
|
15
|
+
Ensures request.user is loaded asynchronously before reaching async views,
|
16
|
+
preventing SynchronousOnlyOperation errors during authentication checks
|
17
|
+
that might involve database access (like session loading).
|
18
|
+
|
19
|
+
This should be placed *after* Django's built-in AuthenticationMiddleware.
|
20
|
+
"""
|
21
|
+
|
22
|
+
# One-time configuration and initialization.
|
23
|
+
# (Not needed for this simple middleware)
|
24
|
+
|
25
|
+
async def middleware(request):
|
26
|
+
# Code to be executed for each request before
|
27
|
+
# the view (and later middleware) are called.
|
28
|
+
|
29
|
+
# Check if request.user is a SimpleLazyObject and hasn't been evaluated yet.
|
30
|
+
# Django's AuthenticationMiddleware sets request.user to a SimpleLazyObject
|
31
|
+
# wrapping the get_user function. Accessing request.user triggers evaluation.
|
32
|
+
if isinstance(request.user, SimpleLazyObject):
|
33
|
+
# Use sync_to_async to safely evaluate the lazy object (which calls
|
34
|
+
# the synchronous get_user function) in an async context.
|
35
|
+
# We don't need the result here, just to trigger the load.
|
36
|
+
try:
|
37
|
+
logger.debug("[AsyncAuthMiddleware] Attempting async user load...")
|
38
|
+
_ = await sync_to_async(request.user._setup)() # Access internal _setup to force load
|
39
|
+
is_auth = await sync_to_async(lambda: getattr(request.user, 'is_authenticated', False))()
|
40
|
+
logger.debug(f"[AsyncAuthMiddleware] User loaded via SimpleLazyObject: {request.user}, Authenticated: {is_auth}")
|
41
|
+
except Exception as e:
|
42
|
+
# Log potential errors during user loading but don't block the request
|
43
|
+
logger.error(f"[AsyncAuthMiddleware] Error during async user load: {e}", exc_info=True)
|
44
|
+
# You might want to handle specific auth errors differently
|
45
|
+
else:
|
46
|
+
# If it's not a SimpleLazyObject, it might be already loaded or AnonymousUser
|
47
|
+
is_auth = getattr(request.user, 'is_authenticated', False)
|
48
|
+
logger.debug(f"[AsyncAuthMiddleware] User already loaded or not lazy: {request.user}, Authenticated: {is_auth}")
|
49
|
+
|
50
|
+
|
51
|
+
response = await get_response(request)
|
52
|
+
|
53
|
+
# Code to be executed for each request/response after
|
54
|
+
# the view is called.
|
55
|
+
|
56
|
+
return response
|
57
|
+
|
58
|
+
# Return the correct function based on whether get_response is async or sync
|
59
|
+
if asyncio.iscoroutinefunction(get_response):
|
60
|
+
return middleware
|
61
|
+
else:
|
62
|
+
# If the next middleware/view is sync, we don't need our async wrapper
|
63
|
+
# However, the decorator handles this, so we just return the async version.
|
64
|
+
# For clarity, the decorator makes this middleware compatible either way.
|
65
|
+
return middleware
|
swarm/settings.py
CHANGED
@@ -28,6 +28,8 @@ ENABLE_API_AUTH = bool(_raw_api_token)
|
|
28
28
|
SWARM_API_KEY = _raw_api_token # Assign the loaded token (or None)
|
29
29
|
|
30
30
|
if ENABLE_API_AUTH:
|
31
|
+
# Add assertion to satisfy type checkers within this block
|
32
|
+
assert SWARM_API_KEY is not None, "SWARM_API_KEY cannot be None when ENABLE_API_AUTH is True"
|
31
33
|
print(f"[Settings] SWARM_API_KEY loaded: {SWARM_API_KEY[:4]}...{SWARM_API_KEY[-4:]}")
|
32
34
|
print("[Settings] ENABLE_API_AUTH is True.")
|
33
35
|
else:
|
@@ -58,6 +60,8 @@ MIDDLEWARE = [
|
|
58
60
|
'django.middleware.common.CommonMiddleware',
|
59
61
|
'django.middleware.csrf.CsrfViewMiddleware',
|
60
62
|
'django.contrib.auth.middleware.AuthenticationMiddleware',
|
63
|
+
# Add custom middleware to handle async user loading after standard auth
|
64
|
+
'swarm.middleware.AsyncAuthMiddleware',
|
61
65
|
'django.contrib.messages.middleware.MessageMiddleware',
|
62
66
|
'django.middleware.clickjacking.XFrameOptionsMiddleware',
|
63
67
|
]
|
File without changes
|
{open_swarm-0.1.1743371918.dist-info → open_swarm-0.1.1743416034.dist-info}/licenses/LICENSE
RENAMED
File without changes
|