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.
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: open-swarm
3
- Version: 0.1.1743371918
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 (Mission Control Platform) 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.
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=rGPcnLSf6WetpeovBb6AhDzWi2GwaFbsQ8UZjRVTMtI,6334
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=LwKVYTRRg6ceNpvbuzM-bl7NukBGNu3bOU9Q3h6WjOU,22834
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.1743371918.dist-info/METADATA,sha256=zGZTjlRSbmYI4EgXVdxetl4cB-LyroVU8o6YDW2Cfic,13680
257
- open_swarm-0.1.1743371918.dist-info/WHEEL,sha256=qtCwoSJWgHk21S1Kb4ihdzI2rlJ1ZKaIurTj_ngOhyQ,87
258
- open_swarm-0.1.1743371918.dist-info/entry_points.txt,sha256=LudR3dBqGnglrE1n2zAeWo38Ck0m57sKPW36KfK-pzo,71
259
- open_swarm-0.1.1743371918.dist-info/licenses/LICENSE,sha256=BU9bwRlnOt_JDIb6OT55Q4leLZx9RArDLTFnlDIrBEI,1062
260
- open_swarm-0.1.1743371918.dist-info/RECORD,,
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,,
@@ -1,2 +1,3 @@
1
1
  [console_scripts]
2
+ swarm-api = swarm.extensions.launchers.swarm_api:main
2
3
  swarm-cli = swarm.extensions.launchers.swarm_cli:app
@@ -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.get_llm_profile(profile_name)
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 = self.config.get("llm_profile", "default")
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
  ]