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.
Files changed (295) hide show
  1. open_swarm-0.1.1748636259.dist-info/METADATA +188 -0
  2. open_swarm-0.1.1748636259.dist-info/RECORD +82 -0
  3. {open_swarm-0.1.1745274976.dist-info → open_swarm-0.1.1748636259.dist-info}/WHEEL +2 -1
  4. open_swarm-0.1.1748636259.dist-info/entry_points.txt +3 -0
  5. open_swarm-0.1.1748636259.dist-info/top_level.txt +1 -0
  6. swarm/agent/agent.py +49 -0
  7. swarm/auth.py +48 -113
  8. swarm/consumers.py +0 -19
  9. swarm/extensions/blueprint/__init__.py +16 -30
  10. swarm/{core → extensions/blueprint}/agent_utils.py +1 -1
  11. swarm/extensions/blueprint/blueprint_base.py +458 -0
  12. swarm/extensions/blueprint/blueprint_discovery.py +112 -0
  13. swarm/extensions/blueprint/output_utils.py +95 -0
  14. swarm/{core → extensions/blueprint}/spinner.py +21 -30
  15. swarm/extensions/cli/cli_args.py +0 -6
  16. swarm/extensions/cli/commands/blueprint_management.py +9 -47
  17. swarm/extensions/cli/commands/config_management.py +6 -5
  18. swarm/extensions/cli/commands/edit_config.py +7 -16
  19. swarm/extensions/cli/commands/list_blueprints.py +1 -1
  20. swarm/extensions/cli/commands/validate_env.py +4 -11
  21. swarm/extensions/cli/commands/validate_envvars.py +6 -6
  22. swarm/extensions/cli/interactive_shell.py +2 -16
  23. swarm/extensions/config/config_loader.py +201 -107
  24. swarm/{core → extensions/config}/config_manager.py +38 -50
  25. swarm/{core → extensions/config}/server_config.py +0 -32
  26. swarm/extensions/launchers/build_launchers.py +14 -0
  27. swarm/{core → extensions/launchers}/build_swarm_wrapper.py +0 -0
  28. swarm/extensions/launchers/swarm_api.py +64 -8
  29. swarm/extensions/launchers/swarm_cli.py +300 -8
  30. swarm/llm/chat_completion.py +195 -0
  31. swarm/serializers.py +5 -96
  32. swarm/settings.py +111 -99
  33. swarm/urls.py +74 -57
  34. swarm/utils/context_utils.py +4 -10
  35. swarm/utils/general_utils.py +0 -21
  36. swarm/utils/redact.py +36 -23
  37. swarm/views/api_views.py +39 -48
  38. swarm/views/chat_views.py +70 -237
  39. swarm/views/core_views.py +87 -80
  40. swarm/views/model_views.py +121 -64
  41. swarm/views/utils.py +441 -65
  42. swarm/views/web_views.py +2 -2
  43. open_swarm-0.1.1745274976.dist-info/METADATA +0 -874
  44. open_swarm-0.1.1745274976.dist-info/RECORD +0 -318
  45. open_swarm-0.1.1745274976.dist-info/entry_points.txt +0 -4
  46. swarm/blueprints/README.md +0 -68
  47. swarm/blueprints/blueprint_audit_status.json +0 -27
  48. swarm/blueprints/chatbot/README.md +0 -40
  49. swarm/blueprints/chatbot/blueprint_chatbot.py +0 -471
  50. swarm/blueprints/chatbot/metadata.json +0 -23
  51. swarm/blueprints/chatbot/templates/chatbot/chatbot.html +0 -33
  52. swarm/blueprints/chucks_angels/README.md +0 -11
  53. swarm/blueprints/chucks_angels/blueprint_chucks_angels.py +0 -7
  54. swarm/blueprints/chucks_angels/test_basic.py +0 -3
  55. swarm/blueprints/codey/CODEY.md +0 -15
  56. swarm/blueprints/codey/README.md +0 -115
  57. swarm/blueprints/codey/blueprint_codey.py +0 -1072
  58. swarm/blueprints/codey/codey_cli.py +0 -373
  59. swarm/blueprints/codey/instructions.md +0 -17
  60. swarm/blueprints/codey/metadata.json +0 -23
  61. swarm/blueprints/common/operation_box_utils.py +0 -83
  62. swarm/blueprints/digitalbutlers/README.md +0 -11
  63. swarm/blueprints/digitalbutlers/__init__.py +0 -1
  64. swarm/blueprints/digitalbutlers/blueprint_digitalbutlers.py +0 -7
  65. swarm/blueprints/digitalbutlers/test_basic.py +0 -3
  66. swarm/blueprints/divine_code/README.md +0 -3
  67. swarm/blueprints/divine_code/__init__.py +0 -10
  68. swarm/blueprints/divine_code/apps.py +0 -11
  69. swarm/blueprints/divine_code/blueprint_divine_code.py +0 -270
  70. swarm/blueprints/django_chat/apps.py +0 -6
  71. swarm/blueprints/django_chat/blueprint_django_chat.py +0 -268
  72. swarm/blueprints/django_chat/templates/django_chat/django_chat_webpage.html +0 -37
  73. swarm/blueprints/django_chat/urls.py +0 -8
  74. swarm/blueprints/django_chat/views.py +0 -32
  75. swarm/blueprints/echocraft/blueprint_echocraft.py +0 -384
  76. swarm/blueprints/flock/README.md +0 -11
  77. swarm/blueprints/flock/__init__.py +0 -8
  78. swarm/blueprints/flock/blueprint_flock.py +0 -7
  79. swarm/blueprints/flock/test_basic.py +0 -3
  80. swarm/blueprints/geese/README.md +0 -97
  81. swarm/blueprints/geese/blueprint_geese.py +0 -803
  82. swarm/blueprints/geese/geese_cli.py +0 -102
  83. swarm/blueprints/jeeves/README.md +0 -41
  84. swarm/blueprints/jeeves/blueprint_jeeves.py +0 -722
  85. swarm/blueprints/jeeves/jeeves_cli.py +0 -55
  86. swarm/blueprints/jeeves/metadata.json +0 -24
  87. swarm/blueprints/mcp_demo/blueprint_mcp_demo.py +0 -473
  88. swarm/blueprints/messenger/templates/messenger/messenger.html +0 -46
  89. swarm/blueprints/mission_improbable/blueprint_mission_improbable.py +0 -423
  90. swarm/blueprints/monkai_magic/blueprint_monkai_magic.py +0 -340
  91. swarm/blueprints/nebula_shellz/blueprint_nebula_shellz.py +0 -265
  92. swarm/blueprints/omniplex/blueprint_omniplex.py +0 -298
  93. swarm/blueprints/poets/blueprint_poets.py +0 -546
  94. swarm/blueprints/poets/poets_cli.py +0 -23
  95. swarm/blueprints/rue_code/README.md +0 -8
  96. swarm/blueprints/rue_code/blueprint_rue_code.py +0 -448
  97. swarm/blueprints/rue_code/rue_code_cli.py +0 -43
  98. swarm/blueprints/stewie/apps.py +0 -12
  99. swarm/blueprints/stewie/blueprint_family_ties.py +0 -349
  100. swarm/blueprints/stewie/models.py +0 -19
  101. swarm/blueprints/stewie/serializers.py +0 -10
  102. swarm/blueprints/stewie/settings.py +0 -17
  103. swarm/blueprints/stewie/urls.py +0 -11
  104. swarm/blueprints/stewie/views.py +0 -26
  105. swarm/blueprints/suggestion/blueprint_suggestion.py +0 -222
  106. swarm/blueprints/whinge_surf/README.md +0 -22
  107. swarm/blueprints/whinge_surf/__init__.py +0 -1
  108. swarm/blueprints/whinge_surf/blueprint_whinge_surf.py +0 -565
  109. swarm/blueprints/whinge_surf/whinge_surf_cli.py +0 -99
  110. swarm/blueprints/whiskeytango_foxtrot/__init__.py +0 -0
  111. swarm/blueprints/whiskeytango_foxtrot/apps.py +0 -11
  112. swarm/blueprints/whiskeytango_foxtrot/blueprint_whiskeytango_foxtrot.py +0 -339
  113. swarm/blueprints/zeus/__init__.py +0 -2
  114. swarm/blueprints/zeus/apps.py +0 -4
  115. swarm/blueprints/zeus/blueprint_zeus.py +0 -270
  116. swarm/blueprints/zeus/zeus_cli.py +0 -13
  117. swarm/cli/async_input.py +0 -65
  118. swarm/cli/async_input_demo.py +0 -32
  119. swarm/core/blueprint_base.py +0 -769
  120. swarm/core/blueprint_discovery.py +0 -125
  121. swarm/core/blueprint_runner.py +0 -59
  122. swarm/core/blueprint_ux.py +0 -109
  123. swarm/core/build_launchers.py +0 -15
  124. swarm/core/cli/__init__.py +0 -1
  125. swarm/core/cli/commands/__init__.py +0 -1
  126. swarm/core/cli/commands/blueprint_management.py +0 -7
  127. swarm/core/cli/interactive_shell.py +0 -14
  128. swarm/core/cli/main.py +0 -50
  129. swarm/core/cli/utils/__init__.py +0 -1
  130. swarm/core/cli/utils/discover_commands.py +0 -18
  131. swarm/core/config_loader.py +0 -122
  132. swarm/core/output_utils.py +0 -193
  133. swarm/core/session_logger.py +0 -42
  134. swarm/core/slash_commands.py +0 -89
  135. swarm/core/swarm_api.py +0 -68
  136. swarm/core/swarm_cli.py +0 -216
  137. swarm/core/utils/__init__.py +0 -0
  138. swarm/extensions/blueprint/cli_handler.py +0 -197
  139. swarm/extensions/blueprint/runnable_blueprint.py +0 -42
  140. swarm/extensions/cli/utils/__init__.py +0 -1
  141. swarm/extensions/cli/utils/async_input.py +0 -46
  142. swarm/extensions/cli/utils/prompt_user.py +0 -3
  143. swarm/management/__init__.py +0 -0
  144. swarm/management/commands/__init__.py +0 -0
  145. swarm/management/commands/runserver.py +0 -58
  146. swarm/middleware.py +0 -65
  147. swarm/permissions.py +0 -38
  148. swarm/static/contrib/fonts/fontawesome-webfont.ttf +0 -7
  149. swarm/static/contrib/fonts/fontawesome-webfont.woff +0 -7
  150. swarm/static/contrib/fonts/fontawesome-webfont.woff2 +0 -7
  151. swarm/static/contrib/markedjs/marked.min.js +0 -6
  152. swarm/static/contrib/tabler-icons/adjustments-horizontal.svg +0 -27
  153. swarm/static/contrib/tabler-icons/alert-triangle.svg +0 -21
  154. swarm/static/contrib/tabler-icons/archive.svg +0 -21
  155. swarm/static/contrib/tabler-icons/artboard.svg +0 -27
  156. swarm/static/contrib/tabler-icons/automatic-gearbox.svg +0 -23
  157. swarm/static/contrib/tabler-icons/box-multiple.svg +0 -19
  158. swarm/static/contrib/tabler-icons/carambola.svg +0 -19
  159. swarm/static/contrib/tabler-icons/copy.svg +0 -20
  160. swarm/static/contrib/tabler-icons/download.svg +0 -21
  161. swarm/static/contrib/tabler-icons/edit.svg +0 -21
  162. swarm/static/contrib/tabler-icons/filled/carambola.svg +0 -13
  163. swarm/static/contrib/tabler-icons/filled/paint.svg +0 -13
  164. swarm/static/contrib/tabler-icons/headset.svg +0 -22
  165. swarm/static/contrib/tabler-icons/layout-sidebar-left-collapse.svg +0 -21
  166. swarm/static/contrib/tabler-icons/layout-sidebar-left-expand.svg +0 -21
  167. swarm/static/contrib/tabler-icons/layout-sidebar-right-collapse.svg +0 -21
  168. swarm/static/contrib/tabler-icons/layout-sidebar-right-expand.svg +0 -21
  169. swarm/static/contrib/tabler-icons/message-chatbot.svg +0 -22
  170. swarm/static/contrib/tabler-icons/message-star.svg +0 -22
  171. swarm/static/contrib/tabler-icons/message-x.svg +0 -23
  172. swarm/static/contrib/tabler-icons/message.svg +0 -21
  173. swarm/static/contrib/tabler-icons/paperclip.svg +0 -18
  174. swarm/static/contrib/tabler-icons/playlist-add.svg +0 -22
  175. swarm/static/contrib/tabler-icons/robot.svg +0 -26
  176. swarm/static/contrib/tabler-icons/search.svg +0 -19
  177. swarm/static/contrib/tabler-icons/settings.svg +0 -20
  178. swarm/static/contrib/tabler-icons/thumb-down.svg +0 -19
  179. swarm/static/contrib/tabler-icons/thumb-up.svg +0 -19
  180. swarm/static/css/dropdown.css +0 -22
  181. swarm/static/htmx/htmx.min.js +0 -0
  182. swarm/static/js/dropdown.js +0 -23
  183. swarm/static/rest_mode/css/base.css +0 -470
  184. swarm/static/rest_mode/css/chat-history.css +0 -286
  185. swarm/static/rest_mode/css/chat.css +0 -251
  186. swarm/static/rest_mode/css/chatbot.css +0 -74
  187. swarm/static/rest_mode/css/chatgpt.css +0 -62
  188. swarm/static/rest_mode/css/colors/corporate.css +0 -74
  189. swarm/static/rest_mode/css/colors/pastel.css +0 -81
  190. swarm/static/rest_mode/css/colors/tropical.css +0 -82
  191. swarm/static/rest_mode/css/general.css +0 -142
  192. swarm/static/rest_mode/css/layout.css +0 -167
  193. swarm/static/rest_mode/css/layouts/messenger-layout.css +0 -17
  194. swarm/static/rest_mode/css/layouts/minimalist-layout.css +0 -57
  195. swarm/static/rest_mode/css/layouts/mobile-layout.css +0 -8
  196. swarm/static/rest_mode/css/messages.css +0 -84
  197. swarm/static/rest_mode/css/messenger.css +0 -135
  198. swarm/static/rest_mode/css/settings.css +0 -91
  199. swarm/static/rest_mode/css/simple.css +0 -44
  200. swarm/static/rest_mode/css/slack.css +0 -58
  201. swarm/static/rest_mode/css/style.css +0 -156
  202. swarm/static/rest_mode/css/theme.css +0 -30
  203. swarm/static/rest_mode/css/toast.css +0 -40
  204. swarm/static/rest_mode/js/auth.js +0 -9
  205. swarm/static/rest_mode/js/blueprint.js +0 -41
  206. swarm/static/rest_mode/js/blueprintUtils.js +0 -12
  207. swarm/static/rest_mode/js/chatLogic.js +0 -79
  208. swarm/static/rest_mode/js/debug.js +0 -63
  209. swarm/static/rest_mode/js/events.js +0 -98
  210. swarm/static/rest_mode/js/main.js +0 -19
  211. swarm/static/rest_mode/js/messages.js +0 -264
  212. swarm/static/rest_mode/js/messengerLogic.js +0 -355
  213. swarm/static/rest_mode/js/modules/apiService.js +0 -84
  214. swarm/static/rest_mode/js/modules/blueprintManager.js +0 -162
  215. swarm/static/rest_mode/js/modules/chatHistory.js +0 -110
  216. swarm/static/rest_mode/js/modules/debugLogger.js +0 -14
  217. swarm/static/rest_mode/js/modules/eventHandlers.js +0 -107
  218. swarm/static/rest_mode/js/modules/messageProcessor.js +0 -120
  219. swarm/static/rest_mode/js/modules/state.js +0 -7
  220. swarm/static/rest_mode/js/modules/userInteractions.js +0 -29
  221. swarm/static/rest_mode/js/modules/validation.js +0 -23
  222. swarm/static/rest_mode/js/rendering.js +0 -119
  223. swarm/static/rest_mode/js/settings.js +0 -130
  224. swarm/static/rest_mode/js/sidebar.js +0 -94
  225. swarm/static/rest_mode/js/simpleLogic.js +0 -37
  226. swarm/static/rest_mode/js/slackLogic.js +0 -66
  227. swarm/static/rest_mode/js/splash.js +0 -76
  228. swarm/static/rest_mode/js/theme.js +0 -111
  229. swarm/static/rest_mode/js/toast.js +0 -36
  230. swarm/static/rest_mode/js/ui.js +0 -265
  231. swarm/static/rest_mode/js/validation.js +0 -57
  232. swarm/static/rest_mode/svg/animated_spinner.svg +0 -12
  233. swarm/static/rest_mode/svg/arrow_down.svg +0 -5
  234. swarm/static/rest_mode/svg/arrow_left.svg +0 -5
  235. swarm/static/rest_mode/svg/arrow_right.svg +0 -5
  236. swarm/static/rest_mode/svg/arrow_up.svg +0 -5
  237. swarm/static/rest_mode/svg/attach.svg +0 -8
  238. swarm/static/rest_mode/svg/avatar.svg +0 -7
  239. swarm/static/rest_mode/svg/canvas.svg +0 -6
  240. swarm/static/rest_mode/svg/chat_history.svg +0 -4
  241. swarm/static/rest_mode/svg/close.svg +0 -5
  242. swarm/static/rest_mode/svg/copy.svg +0 -4
  243. swarm/static/rest_mode/svg/dark_mode.svg +0 -3
  244. swarm/static/rest_mode/svg/edit.svg +0 -5
  245. swarm/static/rest_mode/svg/layout.svg +0 -9
  246. swarm/static/rest_mode/svg/logo.svg +0 -29
  247. swarm/static/rest_mode/svg/logout.svg +0 -5
  248. swarm/static/rest_mode/svg/mobile.svg +0 -5
  249. swarm/static/rest_mode/svg/new_chat.svg +0 -4
  250. swarm/static/rest_mode/svg/not_visible.svg +0 -5
  251. swarm/static/rest_mode/svg/plus.svg +0 -7
  252. swarm/static/rest_mode/svg/run_code.svg +0 -6
  253. swarm/static/rest_mode/svg/save.svg +0 -4
  254. swarm/static/rest_mode/svg/search.svg +0 -6
  255. swarm/static/rest_mode/svg/settings.svg +0 -4
  256. swarm/static/rest_mode/svg/speaker.svg +0 -5
  257. swarm/static/rest_mode/svg/stop.svg +0 -6
  258. swarm/static/rest_mode/svg/thumbs_down.svg +0 -3
  259. swarm/static/rest_mode/svg/thumbs_up.svg +0 -3
  260. swarm/static/rest_mode/svg/toggle_off.svg +0 -6
  261. swarm/static/rest_mode/svg/toggle_on.svg +0 -6
  262. swarm/static/rest_mode/svg/trash.svg +0 -10
  263. swarm/static/rest_mode/svg/undo.svg +0 -3
  264. swarm/static/rest_mode/svg/visible.svg +0 -8
  265. swarm/static/rest_mode/svg/voice.svg +0 -10
  266. swarm/templates/account/login.html +0 -22
  267. swarm/templates/account/signup.html +0 -32
  268. swarm/templates/base.html +0 -30
  269. swarm/templates/chat.html +0 -43
  270. swarm/templates/index.html +0 -35
  271. swarm/templates/rest_mode/components/chat_sidebar.html +0 -55
  272. swarm/templates/rest_mode/components/header.html +0 -45
  273. swarm/templates/rest_mode/components/main_chat_pane.html +0 -41
  274. swarm/templates/rest_mode/components/settings_dialog.html +0 -97
  275. swarm/templates/rest_mode/components/splash_screen.html +0 -7
  276. swarm/templates/rest_mode/components/top_bar.html +0 -28
  277. swarm/templates/rest_mode/message_ui.html +0 -50
  278. swarm/templates/rest_mode/slackbot.html +0 -30
  279. swarm/templates/simple_blueprint_page.html +0 -24
  280. swarm/templates/websocket_partials/final_system_message.html +0 -3
  281. swarm/templates/websocket_partials/system_message.html +0 -4
  282. swarm/templates/websocket_partials/user_message.html +0 -5
  283. swarm/utils/ansi_box.py +0 -34
  284. swarm/utils/disable_tracing.py +0 -38
  285. swarm/utils/log_utils.py +0 -63
  286. swarm/utils/openai_patch.py +0 -33
  287. swarm/ux/ansi_box.py +0 -43
  288. swarm/ux/spinner.py +0 -53
  289. {open_swarm-0.1.1745274976.dist-info → open_swarm-0.1.1748636259.dist-info}/licenses/LICENSE +0 -0
  290. /swarm/{core → extensions/blueprint}/blueprint_utils.py +0 -0
  291. /swarm/{core → extensions/blueprint}/common_utils.py +0 -0
  292. /swarm/{core → extensions/config}/setup_wizard.py +0 -0
  293. /swarm/{blueprints/rue_code → extensions/config/utils}/__init__.py +0 -0
  294. /swarm/{core → extensions/config}/utils/logger.py +0 -0
  295. /swarm/{core → extensions/launchers}/swarm_wrapper.py +0 -0
@@ -0,0 +1,188 @@
1
+ Metadata-Version: 2.4
2
+ Name: open-swarm
3
+ Version: 0.1.1748636259
4
+ Summary: A tool for orchestrating Swarm using both CLI and API.
5
+ Author-email: Matthew Hand <matthewhandau@gmail.com>
6
+ Requires-Python: >=3.10
7
+ Description-Content-Type: text/markdown
8
+ License-File: LICENSE
9
+ Requires-Dist: aiofiles>=24.1.0
10
+ Requires-Dist: aiohttp>=3.11.11
11
+ Requires-Dist: asyncio>=3.4.3
12
+ Requires-Dist: asynctest>=0.13.0
13
+ Requires-Dist: channels>=4.2.0
14
+ Requires-Dist: colorama>=0.4.6
15
+ Requires-Dist: django<5.0,>=4.2
16
+ Requires-Dist: django-allauth>=65.3.1
17
+ Requires-Dist: django-template-debug>=0.3.5
18
+ Requires-Dist: djangorestframework>=3.15.2
19
+ Requires-Dist: flask>=3.1.0
20
+ Requires-Dist: jmespath>=1.0.1
21
+ Requires-Dist: jsonschema-pydantic>=0.6
22
+ Requires-Dist: mcp>=1.2.0
23
+ Requires-Dist: openai>=1.58.1
24
+ Requires-Dist: python-dotenv>=1.0.1
25
+ Requires-Dist: redis>=5.2.1
26
+ Requires-Dist: requests>=2.32.3
27
+ Requires-Dist: whitenoise>=6.8.2
28
+ Requires-Dist: drf-spectacular>=0.23.0
29
+ Requires-Dist: pyinstaller>=6.12.0
30
+ Requires-Dist: tiktoken>=0.9.0
31
+ Requires-Dist: django-cors-headers>=4.7.0
32
+ Requires-Dist: cachetools>=5.5.2
33
+ Requires-Dist: openai-agents
34
+ Provides-Extra: dev
35
+ Requires-Dist: pytest>=8.3.4; extra == "dev"
36
+ Requires-Dist: pytest-asyncio>=0.25.1; extra == "dev"
37
+ Requires-Dist: pytest-cov>=6.0.0; extra == "dev"
38
+ Requires-Dist: pytest-django>=4.9.0; extra == "dev"
39
+ Requires-Dist: pytest-mock>=3.14.0; extra == "dev"
40
+ Requires-Dist: python-semantic-release>=9.20.0; extra == "dev"
41
+ Provides-Extra: experimental
42
+ Requires-Dist: nemoguardrails>=0.11.0; extra == "experimental"
43
+ Dynamic: license-file
44
+
45
+ Open-Swarm Update - 20250328
46
+
47
+ This project is now repurposed due to OpenAI officially supporting the Swarm framework under the new name "openai-agents(-python)".
48
+
49
+ Open-swarm now utilizes the openai-agents framework for enhanced capabilities, and the MCP logic has been offloaded to the openai-agents framework.
50
+
51
+ Key focus areas of this open-swarm framework include:
52
+ - **Blueprints**: A blueprint can be converted into an OpenAI-compatible REST endpoint (analogous to `/v1/chat/completions`, but with agents) and/or into CLI utilities on the shell.
53
+ - **Config Loader**: Blueprints and configuration management form a core aspect of the project.
54
+
55
+ Installation:
56
+ -------------
57
+ Open-swarm is available via PyPI. To install, run:
58
+ ```
59
+ pip install open-swarm
60
+ ```
61
+
62
+ Usage:
63
+ ------
64
+ In development, after cloning the repository (`github.com/matthewhand/open-swarm`), you can run a blueprint directly with:
65
+ ```
66
+ uv run blueprints/mcp_demo/blueprint_mcp_demo.py
67
+ ```
68
+
69
+ To run the blueprint with a specific instruction (for example, to list its tools), execute:
70
+ ```
71
+ uv run blueprints/mcp_demo/blueprint_mcp_demo.py --instruction "list your tools"
72
+ ```
73
+
74
+ Alternatively, you can run the blueprint as an API endpoint using the swarm-api utility:
75
+ ```
76
+ swarm-api --blueprint mcp_demo
77
+ ```
78
+
79
+ In production, you can use the swarm-cli utility to manage and run blueprints. For example, to add an example blueprint:
80
+ ```
81
+ swarm-cli add github:matthewhand/open-swarm/blueprints/mcp_demo
82
+ ```
83
+ This command saves the blueprint to:
84
+ ```
85
+ ~/.swarm/blueprints/mcp_demo/
86
+ ```
87
+ After adding the blueprint, you can convert it into a standalone CLI utility with:
88
+ ```
89
+ swarm-cli install mcp_demo
90
+ ```
91
+
92
+ Building a Basic Blueprint & Config File:
93
+ ------------------------------------------
94
+ You can create your own blueprint to extend open-swarm's capabilities. Here is a walkthrough:
95
+
96
+ 1. **Create a Blueprint File:**
97
+ - In the `blueprints/` directory, create a new Python file, for example `blueprints/my_blueprint.py`.
98
+ - Define a new class that inherits from `BlueprintBase` and implement the required abstract methods, such as `metadata` and `create_agents()`. For instance:
99
+ ```
100
+ from swarm.extensions.blueprint.blueprint_base import BlueprintBase
101
+
102
+ class MyBlueprint(BlueprintBase):
103
+ @property
104
+ def metadata(self):
105
+ return {
106
+ "title": "MyBlueprint",
107
+ "env_vars": [],
108
+ "required_mcp_servers": [],
109
+ "max_context_tokens": 8000,
110
+ "max_context_messages": 50
111
+ }
112
+
113
+ def create_agents(self):
114
+ # Create and return agents as a dictionary.
115
+ return {"MyAgent": ...} # Implement your agent creation logic here.
116
+
117
+ if __name__ == "__main__":
118
+ MyBlueprint.main()
119
+ ```
120
+
121
+ 2. **Create a Configuration File:**
122
+ - Create a configuration file (e.g., `swarm_config.json`) at the root of the project. This file can include settings for LLM models and MCP servers. For example:
123
+ ```
124
+ {
125
+ "llm": {
126
+ "default": {
127
+ "provider": "openai",
128
+ "model": "gpt-4",
129
+ "api_key": "your-openai-api-key",
130
+ "base_url": null
131
+ }
132
+ },
133
+ "mcpServers": {
134
+ "mcp_llms_txt_server": {
135
+ "command": "echo",
136
+ "args": [],
137
+ "env": {}
138
+ },
139
+ "everything_server": {
140
+ "command": "echo",
141
+ "args": [],
142
+ "env": {}
143
+ }
144
+ }
145
+ }
146
+ ```
147
+
148
+ 3. **Running Your Blueprint:**
149
+ - To run your blueprint in development mode, use:
150
+ ```
151
+ uv run blueprints/my_blueprint.py
152
+ ```
153
+ - Ensure your configuration file is properly loaded by your blueprint (this might require modifications in your blueprint's initialization logic or passing a `--config` parameter).
154
+
155
+ Installation & Deployment via swarm-cli:
156
+ --------------------------------------------
157
+ After creating your blueprint and config file, you can manage it with the swarm-cli utility. For example:
158
+ - **Adding your blueprint:**
159
+ ```
160
+ swarm-cli add github:matthewhand/open-swarm/blueprints/my_blueprint
161
+ ```
162
+ - **Installing as a standalone CLI utility:**
163
+ ```
164
+ swarm-cli install my_blueprint
165
+ ```
166
+
167
+ Examples:
168
+ ---------
169
+ **Blueprint "mcp_demo":**
170
+
171
+ The blueprint located in `blueprints/mcp_demo` demonstrates a key design principle:
172
+ - It creates a primary agent named **Sage** that leverages the MCP framework to incorporate external capabilities.
173
+ - **Sage** uses another agent, **Explorer**, as a tool to extend its functionality.
174
+
175
+ This hierarchical agent design illustrates how blueprints can compose agents that call on subagents as tools. This model serves as a prototype for creating powerful agent-driven workflows and can be deployed both as a REST endpoint and as a CLI tool.
176
+
177
+ Production Environment:
178
+ -----------------------
179
+ After installing the package via pip, you can manage blueprints with `swarm-cli` and launch them as standalone utilities or REST services.
180
+
181
+ For help with swarm-cli:
182
+ ```
183
+ swarm-cli --help
184
+ ```
185
+
186
+ For help with swarm-api:
187
+ ```
188
+ swarm-api --help
@@ -0,0 +1,82 @@
1
+ open_swarm-0.1.1748636259.dist-info/licenses/LICENSE,sha256=BU9bwRlnOt_JDIb6OT55Q4leLZx9RArDLTFnlDIrBEI,1062
2
+ swarm/__init__.py,sha256=aT-yyX84tiZhihp0RAXYTADCo9dhOnmolQVfn4_NQa8,46
3
+ swarm/apps.py,sha256=up4C3m2JeyXeUcH-wYeReCuiOBVJ6404w9OfaRChLwM,2568
4
+ swarm/auth.py,sha256=WcajB6lrA2cSA-Ho1lnBEs9_MNtDx713sxHRvIXx9fQ,2415
5
+ swarm/consumers.py,sha256=wESLamkhbi4SEZt9k3yx6eU9ufOIZMCAL-OAXjJBGXE,5056
6
+ swarm/messages.py,sha256=CwADrjlj-uVmm-so1xIZvN1UkEWdzSn_hu7slfhuS8w,6549
7
+ swarm/models.py,sha256=Ix0WEYYqza2lbOEBNesikRCs3XGUPWmqQyMWzZYUaxM,1494
8
+ swarm/serializers.py,sha256=EPvQHvUZtnOKX5ltddNFPGnWaJGxFDWFbofTa39oxgE,363
9
+ swarm/settings.py,sha256=7VUVuzNdmA-QdUwE9nzn2e4a1BIEe21ULNqHt5k00xc,7872
10
+ swarm/tool_executor.py,sha256=KHM2mTGgbbTgWNN3fbV5c4MDY238OTLwaaqtkczFHFQ,12385
11
+ swarm/urls.py,sha256=i7qIwlSMsMSMrOhkbiUfTEL7tdhRFY4g5prfBimKOX0,4085
12
+ swarm/util.py,sha256=G4x2hXopHhB7IdGCkUXGoykYWyiICnjxg7wcr-WqL8I,4644
13
+ swarm/wsgi.py,sha256=REM_u4HpMCkO0ddrOUXgtY-ITL-VTbRB1-WHvFJAtAU,408
14
+ swarm/agent/__init__.py,sha256=YESGu_UXEBxrlQwghodUMN0vmXZDwWMU7DclCUvoklA,104
15
+ swarm/agent/agent.py,sha256=-lGc05pGmveptO4oZoJq_L6XoTAIpxE8knTc6jxRmEQ,1680
16
+ swarm/extensions/__init__.py,sha256=SadbzfxckByaaqzuKPfXMvqmj45-dcMlavlfQYhGnzE,56
17
+ swarm/extensions/blueprint/__init__.py,sha256=-nAm6l7-42eAJYhWkQlcfq2hQB5ipxg2YIyiQRttX3c,1583
18
+ swarm/extensions/blueprint/agent_utils.py,sha256=YWpANYTaFKAK4inWSirRlvzbHwQAH1wNkgW0esHKIeg,542
19
+ swarm/extensions/blueprint/blueprint_base.py,sha256=8ZZxoLBRGi-p_va6nkPwQryYPEr34ISKKbNV8d4odnU,22215
20
+ swarm/extensions/blueprint/blueprint_discovery.py,sha256=ihrIHo4mDaSAUVREXD1y26d5UmPnxVZtBwDGcDJeYrU,5139
21
+ swarm/extensions/blueprint/blueprint_utils.py,sha256=Ef_pu-RYomqzFjMg6LOSPSdbYFCbYXjEoSvK1OT49Eo,702
22
+ swarm/extensions/blueprint/common_utils.py,sha256=jeKcN3lMdrpOYWIpErH3L5am13jHjaImpVvk2b0mps4,462
23
+ swarm/extensions/blueprint/django_utils.py,sha256=ObtkmF1JW4H2OEYa7vC6ussUsMBtDsZTTVeHGHI-GOQ,17457
24
+ swarm/extensions/blueprint/interactive_mode.py,sha256=vGmMuAgC93TLjMi2RkXQ2FkWfIUblyOTFGHmVdGKLSQ,4572
25
+ swarm/extensions/blueprint/output_utils.py,sha256=8OtVE3gEvPeeTu4Juo6Ad6omSlMqSuAtckXXx7P1CyQ,4022
26
+ swarm/extensions/blueprint/spinner.py,sha256=3J0ZrNzoI5O5qR7hnCeRM3dZx2fLb_H3zkoj_AYt5LQ,3394
27
+ swarm/extensions/blueprint/modes/rest_mode.py,sha256=KZuB_j2NfomER7CmlsLBqRipU3DymKY-9RpoGilMH0I,1357
28
+ swarm/extensions/cli/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
29
+ swarm/extensions/cli/blueprint_runner.py,sha256=CG6XfOiDWuc84I_qefBpkwxEs7JcIbvNJqce9jBYUxo,9158
30
+ swarm/extensions/cli/cli_args.py,sha256=Lws6Q3I-DNpzq9qSRN8ylUXg-lWly1SuqDSQF9n50bw,2980
31
+ swarm/extensions/cli/interactive_shell.py,sha256=ocHBP975uqJU5LQyM2IiMVW5lQ387lgYHe3sme9ucX4,1322
32
+ swarm/extensions/cli/main.py,sha256=NnmovA7h1Rj1eDQVYe9AN6-eraIbIclHesNVmQPjdk4,1002
33
+ swarm/extensions/cli/selection.py,sha256=etdG6hJFgnLuvD_sVJvXg8qFcgjzCjyL-vYyxWcU0TI,2002
34
+ swarm/extensions/cli/utils.py,sha256=amDW-jbiM12N-t72j2S0cHP3Mxgoo3nrcwq6CwN9HFY,3290
35
+ swarm/extensions/cli/commands/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
36
+ swarm/extensions/cli/commands/blueprint_management.py,sha256=dLNLLoTjInXQ1m9zRyNxu8NacDgwqYY50GvnhSiMQ_I,1116
37
+ swarm/extensions/cli/commands/config_management.py,sha256=RFu9AP437aqUnyy8RDoyoZgW0WfT7h88_CQJaUnCR9E,480
38
+ swarm/extensions/cli/commands/edit_config.py,sha256=O2Y-BKOSx7shSc-kspyseEQvtIeyQBUCD7Aj3r9dirw,2325
39
+ swarm/extensions/cli/commands/list_blueprints.py,sha256=TyZv_dqM_UTK84-s-Dp7UWUcvWHXsNuxnCRNNNymWio,768
40
+ swarm/extensions/cli/commands/validate_env.py,sha256=VXBjx9etvj4Re8qLwIPoHr4g5VwbwBCBdsr8gGLLYHI,1958
41
+ swarm/extensions/cli/commands/validate_envvars.py,sha256=7-BDPYzV7wsga7kOggHNuCscI-7z-oPjMEBhq-ndDXA,1588
42
+ swarm/extensions/cli/utils/discover_commands.py,sha256=aJdU3kSmLlpBxzGdfOA88AaCwpknHSD2cE0piCHZRUY,1053
43
+ swarm/extensions/cli/utils/env_setup.py,sha256=k7QxRjzIGx5HC6RVZP9QSaaXEKMkcKCewD66u0e7qfE,496
44
+ swarm/extensions/config/__init__.py,sha256=WjmGxMU5k3S40TNQxTfByYcT2YAchq_5gzXFWDLrLzU,141
45
+ swarm/extensions/config/config_loader.py,sha256=A3XCIeLvD7Akp7D1rz-JsBfnW5AvulE-nN-Fop2VsLI,13666
46
+ swarm/extensions/config/config_manager.py,sha256=bBT-NGbRdsXoJ-lxZM5kjAf5FvVVGRVdbbCQJiCX1_0,9951
47
+ swarm/extensions/config/server_config.py,sha256=iBlQOaFQmkEPNLmVpAQvXlSWhTsu-YMIjEf-H-7QfUU,1882
48
+ swarm/extensions/config/setup_wizard.py,sha256=yAZ7MOgc8ZGti2kjZ72G6QLFBI0lbhXAa7Wi7SeXDYo,4567
49
+ swarm/extensions/config/utils/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
50
+ swarm/extensions/config/utils/logger.py,sha256=sUkKdZsjRiCGGCEPfZ4YqeZDbiaUeGFOa3mdbVOTmvU,1242
51
+ swarm/extensions/launchers/__init__.py,sha256=RR4up00HKqXOOToxb63mKZ2o9fq-o75bUw7dZuxkAVk,56
52
+ swarm/extensions/launchers/build_launchers.py,sha256=Eh3ODR9L4KinG1GDK4-lF3NE0EZ-ArCrP3fxtGYhXgs,433
53
+ swarm/extensions/launchers/build_swarm_wrapper.py,sha256=c_9oR3To4M2cZyc1uYSiysHLhUGX5FkCAQk9AG7Va2Q,231
54
+ swarm/extensions/launchers/swarm_api.py,sha256=f8olTI5JVdayp923etVQWsP8WRquPG5Mw3Q40ItN6kY,2877
55
+ swarm/extensions/launchers/swarm_cli.py,sha256=ar0LxctmxUwhkVbKWLfGEcZB9c77qdPsf1Y33-UNgpY,14184
56
+ swarm/extensions/launchers/swarm_wrapper.py,sha256=3K58yqPN4Ct0c7zfSDKRIGdL1Q7WOBXmAVHXT-aaPj4,1004
57
+ swarm/llm/chat_completion.py,sha256=MfeyU7RXJHs8_TBMKxEd7QCnFWjKW7nmWwiNVGMUM0k,9564
58
+ swarm/migrations/0010_initial_chat_models.py,sha256=qJbvLReRBEOE08FkxjOWMcwu7Ny4epNI_eG1PF8wcWM,1900
59
+ swarm/migrations/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
60
+ swarm/repl/__init__.py,sha256=hNU3HxjJJi6w5xgx34n3253QJPspFltrK7AM0G_1TlE,32
61
+ swarm/repl/repl.py,sha256=sfVdSiDrStpZyxZehPn0nAxqaja2eySL9v9CfWhZEVc,2609
62
+ swarm/utils/color_utils.py,sha256=utIfZ6ptGEdpHxIZiZ4gtfo5lLqZKQL5g0F8mEwMhTo,1184
63
+ swarm/utils/context_utils.py,sha256=2Eu372CsuDTt6ikZ0w3OkLrFp4t9hKdgU5Kkc8faDDM,19315
64
+ swarm/utils/general_utils.py,sha256=K3_Uy-189XSpLOxKGxl14fa2n7B0ZH28HgysL6vWG-M,7919
65
+ swarm/utils/logger.py,sha256=g-ynqO3jqKx2rT2keiECsZ13aywFPsFlJAvo-SOeGlw,1679
66
+ swarm/utils/logger_setup.py,sha256=2A9bXicV03yAPpgMFJGQt5ePB1tLwdkk7sCo-0OiglU,714
67
+ swarm/utils/message_sequence.py,sha256=7Xa7YwGPgojfkrGcl-SbeR_BWwzXGDYNqAxq8F6XhDc,8616
68
+ swarm/utils/message_utils.py,sha256=oNTD7pfmnnu_Br24pR2VEX9afIZwFLwg2HJBLXs1blY,4074
69
+ swarm/utils/redact.py,sha256=L2lo927S575Ay7Jz6pUlK47Sxxzpd9IMybnDm6-WlC8,2955
70
+ swarm/views/__init__.py,sha256=AcLk0R7Y69FhIVgJK2hZs8M_gCR-h_5iqUywz89yuHM,1223
71
+ swarm/views/api_views.py,sha256=MXt_sWQYUIYgy6gTHSVIeSrszvhtkD-sxQiGBmdbQAg,1815
72
+ swarm/views/chat_views.py,sha256=Jvwu8Y9sX2t2KkshBBAchXu6dRH8UDV8RAT3zXowVKg,3471
73
+ swarm/views/core_views.py,sha256=VCv5BEBqUMz6OmQC4RkkIk1qq46f5f7Jyx4MqCaoENo,5229
74
+ swarm/views/message_views.py,sha256=sDUnXyqKXC8WwIIMAlWf00s2_a2T9c75Na5FvYMJwBM,1596
75
+ swarm/views/model_views.py,sha256=2bfqF8LOhgWDRFvm5FeovQDdLcZOS9OfkJLvSC0FDvs,6206
76
+ swarm/views/utils.py,sha256=qNt1U5QKC2SFpViqdYwFU2mouklK0MR3W4I979-ES5s,23816
77
+ swarm/views/web_views.py,sha256=ExQQeJpZ8CkLZQC_pXKOOmdnEy2qR3wEBP4LLp27DPU,7404
78
+ open_swarm-0.1.1748636259.dist-info/METADATA,sha256=FsCN1cQScciTDm9aoSzy1O1UabvjSpL87pQBPzxDWGA,6626
79
+ open_swarm-0.1.1748636259.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
80
+ open_swarm-0.1.1748636259.dist-info/entry_points.txt,sha256=tHIcZBvy_sbp_nqZcLG3NSgElG6vEZcUvR5U5325qak,126
81
+ open_swarm-0.1.1748636259.dist-info/top_level.txt,sha256=ETN-2phSZezexCGmKSre_aUhRK0XI9Rzz7Fw5TCsLsQ,6
82
+ open_swarm-0.1.1748636259.dist-info/RECORD,,
@@ -1,4 +1,5 @@
1
1
  Wheel-Version: 1.0
2
- Generator: hatchling 1.27.0
2
+ Generator: setuptools (80.9.0)
3
3
  Root-Is-Purelib: true
4
4
  Tag: py3-none-any
5
+
@@ -0,0 +1,3 @@
1
+ [console_scripts]
2
+ swarm-api = swarm.extensions.launchers.swarm_api:main
3
+ swarm-cli = swarm.extensions.launchers.swarm_cli:main
@@ -0,0 +1 @@
1
+ swarm
swarm/agent/agent.py ADDED
@@ -0,0 +1,49 @@
1
+ # src/swarm/agent/agent.py
2
+
3
+ from typing import Callable, Dict, Any, List
4
+ import json
5
+
6
+ class Agent:
7
+ def __init__(self, name: str, instructions: str):
8
+ self.name = name
9
+ self.instructions = instructions
10
+ self.tools: Dict[str, Dict[str, Any]] = {}
11
+
12
+ def register_tool(self, name: str, func: Callable[..., Any], description: str = ""):
13
+ """
14
+ Registers a tool with the agent.
15
+
16
+ Args:
17
+ name (str): Name of the tool.
18
+ func (Callable[..., Any]): The function implementing the tool.
19
+ description (str): Description of the tool.
20
+ """
21
+ self.tools[name] = {
22
+ "func": func,
23
+ "description": description
24
+ }
25
+
26
+ async def process(self, query: str) -> str:
27
+ """
28
+ Processes a user query by determining which tool to invoke.
29
+
30
+ Args:
31
+ query (str): The user's query in JSON format specifying the tool and arguments.
32
+
33
+ Returns:
34
+ str: The response from the tool execution.
35
+ """
36
+ try:
37
+ request = json.loads(query)
38
+ tool_name = request.get("tool")
39
+ arguments = request.get("arguments", {})
40
+ if tool_name in self.tools:
41
+ tool_func = self.tools[tool_name]["func"]
42
+ result = await tool_func(**arguments)
43
+ return result
44
+ else:
45
+ return f"Tool '{tool_name}' not found."
46
+ except json.JSONDecodeError:
47
+ return "Invalid query format. Expected JSON with 'tool' and 'arguments'."
48
+ except Exception as e:
49
+ return f"Error processing query: {e}"
swarm/auth.py CHANGED
@@ -1,121 +1,56 @@
1
- import logging
2
1
  import os
3
- from rest_framework.authentication import BaseAuthentication, SessionAuthentication
4
- # Import BasePermission for creating custom permissions
5
- from rest_framework.permissions import BasePermission
6
- from rest_framework import exceptions
7
- from django.conf import settings
8
- from django.utils.translation import gettext_lazy as _
9
- # Import AnonymousUser
2
+ import logging
10
3
  from django.contrib.auth.models import AnonymousUser
11
- # Keep get_user_model if CustomSessionAuthentication needs it or for future user mapping
12
- from django.contrib.auth import get_user_model
4
+ from rest_framework.authentication import TokenAuthentication # type: ignore
5
+ from rest_framework.exceptions import AuthenticationFailed # type: ignore
13
6
 
14
- logger = logging.getLogger('swarm.auth')
15
- User = get_user_model()
7
+ logger = logging.getLogger(__name__)
16
8
 
17
- # ==============================================================================
18
- # Authentication Classes (Determine *who* the user is)
19
- # ==============================================================================
9
+ class EnvAuthenticatedUser(AnonymousUser):
10
+ """ Custom user class that is always authenticated. """
11
+ @property
12
+ def is_authenticated(self) -> bool: # type: ignore[override]
13
+ return True # Ensure Django recognizes this user as authenticated
20
14
 
21
- # --- Static Token Authentication ---
22
- class StaticTokenAuthentication(BaseAuthentication):
15
+ class EnvOrTokenAuthentication(TokenAuthentication):
23
16
  """
24
- Authenticates requests based on a static API token passed in a header
25
- (Authorization: Bearer <token> or X-API-Key: <token>).
26
-
27
- Returns (AnonymousUser, token) on success. This allows permission classes
28
- to check request.auth to see if token authentication succeeded, even though
29
- no specific user model is associated with the token.
17
+ Custom authentication that allows:
18
+ 1. If API_AUTH_TOKEN is set, it enforces token authentication.
19
+ 2. Else if ENABLE_API_AUTH is False/Unset, authentication is bypassed.
20
+ 3. Otherwise, falls back to Django's TokenAuthentication.
30
21
  """
31
- keyword = 'Bearer'
32
-
33
22
  def authenticate(self, request):
34
- """
35
- Attempts to authenticate using a static token.
36
- """
37
- logger.debug("[Auth][StaticToken] Attempting static token authentication.")
38
- # Retrieve the expected token from settings.
39
- expected_token = getattr(settings, 'SWARM_API_KEY', None)
40
-
41
- # If no token is configured in settings, this method cannot authenticate.
42
- if not expected_token:
43
- logger.error("[Auth][StaticToken] SWARM_API_KEY is not set in Django settings. Cannot use static token auth.")
44
- return None # Indicate authentication method did not run or failed pre-check
45
-
46
- # Extract the provided token from standard Authorization header or custom X-API-Key header.
47
- provided_token = None
48
- auth_header = request.META.get('HTTP_AUTHORIZATION', '').split()
49
- if len(auth_header) == 2 and auth_header[0].lower() == self.keyword.lower():
50
- provided_token = auth_header[1]
51
- logger.debug("[Auth][StaticToken] Found token in Authorization header.")
52
- else:
53
- provided_token = request.META.get('HTTP_X_API_KEY')
54
- if provided_token:
55
- logger.debug("[Auth][StaticToken] Found token in X-API-Key header.")
56
-
57
- # If no token was found in either header, authentication fails for this method.
58
- if not provided_token:
59
- logger.debug("[Auth][StaticToken] No token found in relevant headers.")
60
- return None # Indicate authentication method did not find credentials
61
-
62
- # Compare the provided token with the expected token.
63
- # NOTE: For production, consider using a constant-time comparison function
64
- # to mitigate timing attacks if the token is highly sensitive.
65
- if provided_token == expected_token:
66
- logger.info("[Auth][StaticToken] Static token authentication successful.")
67
- # Return AnonymousUser and the token itself as request.auth.
68
- # This signals successful authentication via token without linking to a specific User model.
69
- return (AnonymousUser(), provided_token)
70
- else:
71
- # Token was provided but did not match. Raise AuthenticationFailed.
72
- logger.warning(f"[Auth][StaticToken] Invalid static token provided.")
73
- raise exceptions.AuthenticationFailed(_("Invalid API Key."))
74
-
75
- # --- Custom *Synchronous* Session Authentication ---
76
- class CustomSessionAuthentication(SessionAuthentication):
77
- """
78
- Standard Django Session Authentication provided by DRF.
79
- Relies on Django's session middleware to populate request.user.
80
- This class itself is synchronous, but the underlying session loading
81
- needs to be handled correctly in async views (e.g., via middleware or wrappers).
82
- """
83
- # No override needed unless customizing session behavior.
84
- pass
85
-
86
-
87
- # ==============================================================================
88
- # Permission Classes (Determine *if* access is allowed)
89
- # ==============================================================================
90
-
91
- class HasValidTokenOrSession(BasePermission):
92
- """
93
- Allows access if EITHER:
94
- 1. Static token authentication succeeded (request.auth is not None).
95
- 2. Session authentication succeeded (request.user is authenticated).
96
- """
97
- message = 'Authentication credentials were not provided or are invalid (Requires valid API Key or active session).'
98
-
99
- def has_permission(self, request, view):
100
- """
101
- Checks if the request has valid authentication via token or session.
102
- """
103
- # Check if static token authentication was successful.
104
- # StaticTokenAuthentication returns (AnonymousUser, token), so request.auth will be the token.
105
- has_valid_token = getattr(request, 'auth', None) is not None
106
- if has_valid_token:
107
- logger.debug("[Perm][TokenOrSession] Access granted via static token (request.auth is set).")
108
- return True
109
-
110
- # Check if session authentication was successful.
111
- # request.user should be populated by SessionAuthentication/AuthMiddleware.
112
- user = getattr(request, 'user', None)
113
- has_valid_session = user is not None and user.is_authenticated
114
- if has_valid_session:
115
- logger.debug(f"[Perm][TokenOrSession] Access granted via authenticated session user: {user}")
116
- return True
117
-
118
- # If neither condition is met, deny permission.
119
- logger.debug("[Perm][TokenOrSession] Access denied: No valid token (request.auth=None) and no authenticated session user.")
120
- return False
121
-
23
+ auth_header = request.headers.get("Authorization", "")
24
+ env_token = os.getenv("API_AUTH_TOKEN", None)
25
+ enable_auth = os.getenv("ENABLE_API_AUTH", "false").lower() in ("true", "1", "t")
26
+
27
+ # If API authentication is disabled, allow unrestricted access
28
+ if not enable_auth:
29
+ logger.info("Authentication is disabled (ENABLE_API_AUTH not set or False). Allowing all users.")
30
+ return (EnvAuthenticatedUser(), None)
31
+
32
+ # If API_AUTH_TOKEN is set, enforce token validation
33
+ if env_token:
34
+ if not auth_header:
35
+ raise AuthenticationFailed("Authentication credentials were not provided.")
36
+ if not auth_header.startswith("Bearer "):
37
+ raise AuthenticationFailed("Invalid token format.")
38
+
39
+ token = auth_header.split("Bearer ")[-1].strip()
40
+
41
+ if token == env_token:
42
+ logger.info("Authenticated using API_AUTH_TOKEN.")
43
+ return (EnvAuthenticatedUser(), None) # Allow access
44
+ else:
45
+ raise AuthenticationFailed("Invalid token.")
46
+
47
+ # If API authentication is disabled, allow unrestricted access
48
+ if not enable_auth:
49
+ logger.info("Authentication is disabled (ENABLE_API_AUTH not set or False). Allowing all users.")
50
+ return (EnvAuthenticatedUser(), None)
51
+
52
+ # Fallback to Django's TokenAuthentication
53
+ return super().authenticate(request)
54
+
55
+ def authenticate_header(self, request):
56
+ return "Bearer"
swarm/consumers.py CHANGED
@@ -62,25 +62,6 @@ class DjangoChatConsumer(AsyncWebsocketConsumer):
62
62
  await self.send(text_data=system_message_html)
63
63
 
64
64
  client = AsyncOpenAI(api_key=os.getenv("OPENAI_API_KEY"))
65
-
66
- # --- PATCH: Enforce LiteLLM-only endpoint and suppress OpenAI tracing/telemetry ---
67
- import os, logging
68
- if os.environ.get("LITELLM_BASE_URL") or os.environ.get("OPENAI_BASE_URL"):
69
- logging.getLogger("openai.agents").setLevel(logging.CRITICAL)
70
- try:
71
- import openai.agents.tracing
72
- openai.agents.tracing.TracingClient = lambda *a, **kw: None
73
- except Exception:
74
- pass
75
- def _enforce_litellm_only(client):
76
- base_url = getattr(client, 'base_url', None)
77
- if base_url and 'openai.com' in base_url:
78
- return
79
- if base_url and 'openai.com' not in base_url:
80
- import traceback
81
- raise RuntimeError(f"Attempted fallback to OpenAI API when custom base_url is set! base_url={base_url}\n{traceback.format_stack()}")
82
- _enforce_litellm_only(client)
83
-
84
65
  stream = await client.chat.completions.create(
85
66
  model=os.getenv("OPENAI_MODEL"),
86
67
  messages=self.messages,
@@ -1,49 +1,35 @@
1
1
  """
2
- Blueprint Extension Package for Open Swarm.
3
-
4
- Provides the base class, discovery mechanisms, and utilities for creating
5
- and running autonomous agent workflows (blueprints).
2
+ Blueprint discovery and management utilities.
6
3
  """
7
4
 
8
- # Core components
9
- from swarm.core.blueprint_base import BlueprintBase
5
+ from .blueprint_base import BlueprintBase
10
6
  from .blueprint_discovery import discover_blueprints
11
7
  from .blueprint_utils import filter_blueprints
12
8
 
13
- # Helper modules (primarily used internally by BlueprintBase or CLI)
14
- from . import config_loader
15
- from . import cli_handler
16
- # from . import interactive_mode # If interactive mode is refactored out
17
- # from . import output_utils # If output utils are used externally
18
-
19
- # Re-export essential message utilities if they are part of the public API
20
- # of this extension package. If they are purely internal utilities,
21
- # they don't necessarily need to be re-exported here.
9
+ # Re-export the necessary message utilities from their new locations
10
+ # Note: The specific truncation functions like truncate_preserve_pairs might have been
11
+ # consolidated into truncate_message_history. Adjust if needed.
22
12
  try:
23
13
  from swarm.utils.message_sequence import repair_message_payload, validate_message_sequence
24
14
  from swarm.utils.context_utils import truncate_message_history
15
+ # If specific old truncation functions are truly needed, they'd have to be
16
+ # re-implemented or their callers refactored to use truncate_message_history.
17
+ # Assuming truncate_message_history is the intended replacement for now.
18
+ # Define aliases if old names are required by downstream code:
19
+ # truncate_preserve_pairs = truncate_message_history # Example if needed
25
20
  except ImportError as e:
21
+ # Log an error or warning if imports fail, helpful for debugging setup issues
26
22
  import logging
27
- logging.getLogger(__name__).warning(f"Could not import core message utilities: {e}")
28
- # Define dummy functions or let importers handle the ImportError
29
- def repair_message_payload(m, **kwargs): raise NotImplementedError from e
30
- def validate_message_sequence(m): raise NotImplementedError from e
31
- def truncate_message_history(m, *args, **kwargs): raise NotImplementedError from e
32
-
23
+ logging.getLogger(__name__).error(f"Failed to import core message utilities: {e}")
24
+ # Define dummy functions or raise error if critical
25
+ def repair_message_payload(m, **kwargs): return m
26
+ def validate_message_sequence(m): return m
27
+ def truncate_message_history(m, *args, **kwargs): return m
33
28
 
34
29
  __all__ = [
35
- # Core
36
30
  "BlueprintBase",
37
31
  "discover_blueprints",
38
32
  "filter_blueprints",
39
-
40
- # Helper Modules (Exporting for potential external use, though less common)
41
- "config_loader",
42
- "cli_handler",
43
- # "interactive_mode",
44
- # "output_utils",
45
-
46
- # Utility Functions (If considered part of the public API)
47
33
  "repair_message_payload",
48
34
  "validate_message_sequence",
49
35
  "truncate_message_history",
@@ -6,7 +6,7 @@ This module has been updated to remove dependency on swarm.types;
6
6
  instead, it now imports Agent from the openai-agents SDK.
7
7
  """
8
8
 
9
- from blueprint_agents.agent import Agent # Updated import
9
+ from agents.agent import Agent # Updated import
10
10
 
11
11
  def get_agent_name(agent: Agent) -> str:
12
12
  """