open-swarm 0.1.1743371228__tar.gz → 0.1.1743372974__tar.gz

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 (320) hide show
  1. {open_swarm-0.1.1743371228 → open_swarm-0.1.1743372974}/PKG-INFO +2 -2
  2. {open_swarm-0.1.1743371228 → open_swarm-0.1.1743372974}/README.md +1 -1
  3. {open_swarm-0.1.1743371228 → open_swarm-0.1.1743372974}/pyproject.toml +4 -1
  4. open_swarm-0.1.1743372974/src/swarm/blueprints/echocraft/blueprint_echocraft.py +71 -0
  5. open_swarm-0.1.1743372974/src/swarm/extensions/blueprint/blueprint_base.py +111 -0
  6. open_swarm-0.1.1743372974/tests/blueprints/test_echocraft.py +76 -0
  7. open_swarm-0.1.1743372974/tests/cli/test_launchers.py +206 -0
  8. open_swarm-0.1.1743372974/tests/unit/test_blueprint_base_config.py +106 -0
  9. open_swarm-0.1.1743371228/src/swarm/blueprints/echocraft/blueprint_echocraft.py +0 -44
  10. open_swarm-0.1.1743371228/src/swarm/extensions/blueprint/blueprint_base.py +0 -160
  11. open_swarm-0.1.1743371228/tests/blueprints/test_echocraft.py +0 -75
  12. open_swarm-0.1.1743371228/tests/cli/test_launchers.py +0 -174
  13. open_swarm-0.1.1743371228/tests/unit/test_blueprint_base_config.py +0 -112
  14. {open_swarm-0.1.1743371228 → open_swarm-0.1.1743372974}/.gitignore +0 -0
  15. {open_swarm-0.1.1743371228 → open_swarm-0.1.1743372974}/LICENSE +0 -0
  16. {open_swarm-0.1.1743371228 → open_swarm-0.1.1743372974}/src/swarm/__init__.py +0 -0
  17. {open_swarm-0.1.1743371228 → open_swarm-0.1.1743372974}/src/swarm/agent/__init__.py +0 -0
  18. {open_swarm-0.1.1743371228 → open_swarm-0.1.1743372974}/src/swarm/apps.py +0 -0
  19. {open_swarm-0.1.1743371228 → open_swarm-0.1.1743372974}/src/swarm/auth.py +0 -0
  20. {open_swarm-0.1.1743371228 → open_swarm-0.1.1743372974}/src/swarm/blueprints/README.md +0 -0
  21. {open_swarm-0.1.1743371228 → open_swarm-0.1.1743372974}/src/swarm/blueprints/burnt_noodles/blueprint_burnt_noodles.py +0 -0
  22. {open_swarm-0.1.1743371228 → open_swarm-0.1.1743372974}/src/swarm/blueprints/chatbot/blueprint_chatbot.py +0 -0
  23. {open_swarm-0.1.1743371228 → open_swarm-0.1.1743372974}/src/swarm/blueprints/chatbot/templates/chatbot/chatbot.html +0 -0
  24. {open_swarm-0.1.1743371228 → open_swarm-0.1.1743372974}/src/swarm/blueprints/digitalbutlers/blueprint_digitalbutlers.py +0 -0
  25. {open_swarm-0.1.1743371228 → open_swarm-0.1.1743372974}/src/swarm/blueprints/dilbot_universe/blueprint_dilbot_universe.py +0 -0
  26. {open_swarm-0.1.1743371228 → open_swarm-0.1.1743372974}/src/swarm/blueprints/divine_code/__init__.py +0 -0
  27. {open_swarm-0.1.1743371228 → open_swarm-0.1.1743372974}/src/swarm/blueprints/divine_code/apps.py +0 -0
  28. {open_swarm-0.1.1743371228 → open_swarm-0.1.1743372974}/src/swarm/blueprints/divine_code/blueprint_divine_code.py +0 -0
  29. {open_swarm-0.1.1743371228 → open_swarm-0.1.1743372974}/src/swarm/blueprints/django_chat/apps.py +0 -0
  30. {open_swarm-0.1.1743371228 → open_swarm-0.1.1743372974}/src/swarm/blueprints/django_chat/blueprint_django_chat.py +0 -0
  31. {open_swarm-0.1.1743371228 → open_swarm-0.1.1743372974}/src/swarm/blueprints/django_chat/templates/django_chat/django_chat_webpage.html +0 -0
  32. {open_swarm-0.1.1743371228 → open_swarm-0.1.1743372974}/src/swarm/blueprints/django_chat/urls.py +0 -0
  33. {open_swarm-0.1.1743371228 → open_swarm-0.1.1743372974}/src/swarm/blueprints/django_chat/views.py +0 -0
  34. {open_swarm-0.1.1743371228 → open_swarm-0.1.1743372974}/src/swarm/blueprints/family_ties/apps.py +0 -0
  35. {open_swarm-0.1.1743371228 → open_swarm-0.1.1743372974}/src/swarm/blueprints/family_ties/blueprint_family_ties.py +0 -0
  36. {open_swarm-0.1.1743371228 → open_swarm-0.1.1743372974}/src/swarm/blueprints/family_ties/models.py +0 -0
  37. {open_swarm-0.1.1743371228 → open_swarm-0.1.1743372974}/src/swarm/blueprints/family_ties/serializers.py +0 -0
  38. {open_swarm-0.1.1743371228 → open_swarm-0.1.1743372974}/src/swarm/blueprints/family_ties/settings.py +0 -0
  39. {open_swarm-0.1.1743371228 → open_swarm-0.1.1743372974}/src/swarm/blueprints/family_ties/urls.py +0 -0
  40. {open_swarm-0.1.1743371228 → open_swarm-0.1.1743372974}/src/swarm/blueprints/family_ties/views.py +0 -0
  41. {open_swarm-0.1.1743371228 → open_swarm-0.1.1743372974}/src/swarm/blueprints/flock/__init__.py +0 -0
  42. {open_swarm-0.1.1743371228 → open_swarm-0.1.1743372974}/src/swarm/blueprints/gaggle/blueprint_gaggle.py +0 -0
  43. {open_swarm-0.1.1743371228 → open_swarm-0.1.1743372974}/src/swarm/blueprints/gotchaman/blueprint_gotchaman.py +0 -0
  44. {open_swarm-0.1.1743371228 → open_swarm-0.1.1743372974}/src/swarm/blueprints/mcp_demo/blueprint_mcp_demo.py +0 -0
  45. {open_swarm-0.1.1743371228 → open_swarm-0.1.1743372974}/src/swarm/blueprints/messenger/templates/messenger/messenger.html +0 -0
  46. {open_swarm-0.1.1743371228 → open_swarm-0.1.1743372974}/src/swarm/blueprints/mission_improbable/blueprint_mission_improbable.py +0 -0
  47. {open_swarm-0.1.1743371228 → open_swarm-0.1.1743372974}/src/swarm/blueprints/monkai_magic/blueprint_monkai_magic.py +0 -0
  48. {open_swarm-0.1.1743371228 → open_swarm-0.1.1743372974}/src/swarm/blueprints/nebula_shellz/blueprint_nebula_shellz.py +0 -0
  49. {open_swarm-0.1.1743371228 → open_swarm-0.1.1743372974}/src/swarm/blueprints/omniplex/blueprint_omniplex.py +0 -0
  50. {open_swarm-0.1.1743371228 → open_swarm-0.1.1743372974}/src/swarm/blueprints/rue_code/__init__.py +0 -0
  51. {open_swarm-0.1.1743371228 → open_swarm-0.1.1743372974}/src/swarm/blueprints/rue_code/blueprint_rue_code.py +0 -0
  52. {open_swarm-0.1.1743371228 → open_swarm-0.1.1743372974}/src/swarm/blueprints/suggestion/blueprint_suggestion.py +0 -0
  53. {open_swarm-0.1.1743371228 → open_swarm-0.1.1743372974}/src/swarm/blueprints/unapologetic_press/blueprint_unapologetic_press.py +0 -0
  54. {open_swarm-0.1.1743371228 → open_swarm-0.1.1743372974}/src/swarm/blueprints/whiskeytango_foxtrot/__init__.py +0 -0
  55. {open_swarm-0.1.1743371228 → open_swarm-0.1.1743372974}/src/swarm/blueprints/whiskeytango_foxtrot/apps.py +0 -0
  56. {open_swarm-0.1.1743371228 → open_swarm-0.1.1743372974}/src/swarm/blueprints/whiskeytango_foxtrot/blueprint_whiskeytango_foxtrot.py +0 -0
  57. {open_swarm-0.1.1743371228 → open_swarm-0.1.1743372974}/src/swarm/consumers.py +0 -0
  58. {open_swarm-0.1.1743371228 → open_swarm-0.1.1743372974}/src/swarm/extensions/__init__.py +0 -0
  59. {open_swarm-0.1.1743371228 → open_swarm-0.1.1743372974}/src/swarm/extensions/blueprint/__init__.py +0 -0
  60. {open_swarm-0.1.1743371228 → open_swarm-0.1.1743372974}/src/swarm/extensions/blueprint/agent_utils.py +0 -0
  61. {open_swarm-0.1.1743371228 → open_swarm-0.1.1743372974}/src/swarm/extensions/blueprint/blueprint_discovery.py +0 -0
  62. {open_swarm-0.1.1743371228 → open_swarm-0.1.1743372974}/src/swarm/extensions/blueprint/blueprint_utils.py +0 -0
  63. {open_swarm-0.1.1743371228 → open_swarm-0.1.1743372974}/src/swarm/extensions/blueprint/cli_handler.py +0 -0
  64. {open_swarm-0.1.1743371228 → open_swarm-0.1.1743372974}/src/swarm/extensions/blueprint/common_utils.py +0 -0
  65. {open_swarm-0.1.1743371228 → open_swarm-0.1.1743372974}/src/swarm/extensions/blueprint/config_loader.py +0 -0
  66. {open_swarm-0.1.1743371228 → open_swarm-0.1.1743372974}/src/swarm/extensions/blueprint/django_utils.py +0 -0
  67. {open_swarm-0.1.1743371228 → open_swarm-0.1.1743372974}/src/swarm/extensions/blueprint/interactive_mode.py +0 -0
  68. {open_swarm-0.1.1743371228 → open_swarm-0.1.1743372974}/src/swarm/extensions/blueprint/modes/rest_mode.py +0 -0
  69. {open_swarm-0.1.1743371228 → open_swarm-0.1.1743372974}/src/swarm/extensions/blueprint/output_utils.py +0 -0
  70. {open_swarm-0.1.1743371228 → open_swarm-0.1.1743372974}/src/swarm/extensions/blueprint/spinner.py +0 -0
  71. {open_swarm-0.1.1743371228 → open_swarm-0.1.1743372974}/src/swarm/extensions/cli/__init__.py +0 -0
  72. {open_swarm-0.1.1743371228 → open_swarm-0.1.1743372974}/src/swarm/extensions/cli/blueprint_runner.py +0 -0
  73. {open_swarm-0.1.1743371228 → open_swarm-0.1.1743372974}/src/swarm/extensions/cli/cli_args.py +0 -0
  74. {open_swarm-0.1.1743371228 → open_swarm-0.1.1743372974}/src/swarm/extensions/cli/commands/__init__.py +0 -0
  75. {open_swarm-0.1.1743371228 → open_swarm-0.1.1743372974}/src/swarm/extensions/cli/commands/blueprint_management.py +0 -0
  76. {open_swarm-0.1.1743371228 → open_swarm-0.1.1743372974}/src/swarm/extensions/cli/commands/config_management.py +0 -0
  77. {open_swarm-0.1.1743371228 → open_swarm-0.1.1743372974}/src/swarm/extensions/cli/commands/edit_config.py +0 -0
  78. {open_swarm-0.1.1743371228 → open_swarm-0.1.1743372974}/src/swarm/extensions/cli/commands/list_blueprints.py +0 -0
  79. {open_swarm-0.1.1743371228 → open_swarm-0.1.1743372974}/src/swarm/extensions/cli/commands/validate_env.py +0 -0
  80. {open_swarm-0.1.1743371228 → open_swarm-0.1.1743372974}/src/swarm/extensions/cli/commands/validate_envvars.py +0 -0
  81. {open_swarm-0.1.1743371228 → open_swarm-0.1.1743372974}/src/swarm/extensions/cli/interactive_shell.py +0 -0
  82. {open_swarm-0.1.1743371228 → open_swarm-0.1.1743372974}/src/swarm/extensions/cli/main.py +0 -0
  83. {open_swarm-0.1.1743371228 → open_swarm-0.1.1743372974}/src/swarm/extensions/cli/selection.py +0 -0
  84. {open_swarm-0.1.1743371228 → open_swarm-0.1.1743372974}/src/swarm/extensions/cli/utils/discover_commands.py +0 -0
  85. {open_swarm-0.1.1743371228 → open_swarm-0.1.1743372974}/src/swarm/extensions/cli/utils/env_setup.py +0 -0
  86. {open_swarm-0.1.1743371228 → open_swarm-0.1.1743372974}/src/swarm/extensions/cli/utils.py +0 -0
  87. {open_swarm-0.1.1743371228 → open_swarm-0.1.1743372974}/src/swarm/extensions/config/__init__.py +0 -0
  88. {open_swarm-0.1.1743371228 → open_swarm-0.1.1743372974}/src/swarm/extensions/config/config_loader.py +0 -0
  89. {open_swarm-0.1.1743371228 → open_swarm-0.1.1743372974}/src/swarm/extensions/config/config_manager.py +0 -0
  90. {open_swarm-0.1.1743371228 → open_swarm-0.1.1743372974}/src/swarm/extensions/config/server_config.py +0 -0
  91. {open_swarm-0.1.1743371228 → open_swarm-0.1.1743372974}/src/swarm/extensions/config/setup_wizard.py +0 -0
  92. {open_swarm-0.1.1743371228 → open_swarm-0.1.1743372974}/src/swarm/extensions/config/utils/__init__.py +0 -0
  93. {open_swarm-0.1.1743371228 → open_swarm-0.1.1743372974}/src/swarm/extensions/config/utils/logger.py +0 -0
  94. {open_swarm-0.1.1743371228 → open_swarm-0.1.1743372974}/src/swarm/extensions/launchers/__init__.py +0 -0
  95. {open_swarm-0.1.1743371228 → open_swarm-0.1.1743372974}/src/swarm/extensions/launchers/build_launchers.py +0 -0
  96. {open_swarm-0.1.1743371228 → open_swarm-0.1.1743372974}/src/swarm/extensions/launchers/build_swarm_wrapper.py +0 -0
  97. {open_swarm-0.1.1743371228 → open_swarm-0.1.1743372974}/src/swarm/extensions/launchers/swarm_api.py +0 -0
  98. {open_swarm-0.1.1743371228 → open_swarm-0.1.1743372974}/src/swarm/extensions/launchers/swarm_cli.py +0 -0
  99. {open_swarm-0.1.1743371228 → open_swarm-0.1.1743372974}/src/swarm/extensions/launchers/swarm_wrapper.py +0 -0
  100. {open_swarm-0.1.1743371228 → open_swarm-0.1.1743372974}/src/swarm/llm/chat_completion.py +0 -0
  101. {open_swarm-0.1.1743371228 → open_swarm-0.1.1743372974}/src/swarm/management/__init__.py +0 -0
  102. {open_swarm-0.1.1743371228 → open_swarm-0.1.1743372974}/src/swarm/management/commands/__init__.py +0 -0
  103. {open_swarm-0.1.1743371228 → open_swarm-0.1.1743372974}/src/swarm/management/commands/runserver.py +0 -0
  104. {open_swarm-0.1.1743371228 → open_swarm-0.1.1743372974}/src/swarm/messages.py +0 -0
  105. {open_swarm-0.1.1743371228 → open_swarm-0.1.1743372974}/src/swarm/migrations/0010_initial_chat_models.py +0 -0
  106. {open_swarm-0.1.1743371228 → open_swarm-0.1.1743372974}/src/swarm/migrations/__init__.py +0 -0
  107. {open_swarm-0.1.1743371228 → open_swarm-0.1.1743372974}/src/swarm/models.py +0 -0
  108. {open_swarm-0.1.1743371228 → open_swarm-0.1.1743372974}/src/swarm/permissions.py +0 -0
  109. {open_swarm-0.1.1743371228 → open_swarm-0.1.1743372974}/src/swarm/repl/__init__.py +0 -0
  110. {open_swarm-0.1.1743371228 → open_swarm-0.1.1743372974}/src/swarm/repl/repl.py +0 -0
  111. {open_swarm-0.1.1743371228 → open_swarm-0.1.1743372974}/src/swarm/serializers.py +0 -0
  112. {open_swarm-0.1.1743371228 → open_swarm-0.1.1743372974}/src/swarm/settings.py +0 -0
  113. {open_swarm-0.1.1743371228 → open_swarm-0.1.1743372974}/src/swarm/static/contrib/fonts/fontawesome-webfont.ttf +0 -0
  114. {open_swarm-0.1.1743371228 → open_swarm-0.1.1743372974}/src/swarm/static/contrib/fonts/fontawesome-webfont.woff +0 -0
  115. {open_swarm-0.1.1743371228 → open_swarm-0.1.1743372974}/src/swarm/static/contrib/fonts/fontawesome-webfont.woff2 +0 -0
  116. {open_swarm-0.1.1743371228 → open_swarm-0.1.1743372974}/src/swarm/static/contrib/markedjs/marked.min.js +0 -0
  117. {open_swarm-0.1.1743371228 → open_swarm-0.1.1743372974}/src/swarm/static/contrib/tabler-icons/adjustments-horizontal.svg +0 -0
  118. {open_swarm-0.1.1743371228 → open_swarm-0.1.1743372974}/src/swarm/static/contrib/tabler-icons/alert-triangle.svg +0 -0
  119. {open_swarm-0.1.1743371228 → open_swarm-0.1.1743372974}/src/swarm/static/contrib/tabler-icons/archive.svg +0 -0
  120. {open_swarm-0.1.1743371228 → open_swarm-0.1.1743372974}/src/swarm/static/contrib/tabler-icons/artboard.svg +0 -0
  121. {open_swarm-0.1.1743371228 → open_swarm-0.1.1743372974}/src/swarm/static/contrib/tabler-icons/automatic-gearbox.svg +0 -0
  122. {open_swarm-0.1.1743371228 → open_swarm-0.1.1743372974}/src/swarm/static/contrib/tabler-icons/box-multiple.svg +0 -0
  123. {open_swarm-0.1.1743371228 → open_swarm-0.1.1743372974}/src/swarm/static/contrib/tabler-icons/carambola.svg +0 -0
  124. {open_swarm-0.1.1743371228 → open_swarm-0.1.1743372974}/src/swarm/static/contrib/tabler-icons/copy.svg +0 -0
  125. {open_swarm-0.1.1743371228 → open_swarm-0.1.1743372974}/src/swarm/static/contrib/tabler-icons/download.svg +0 -0
  126. {open_swarm-0.1.1743371228 → open_swarm-0.1.1743372974}/src/swarm/static/contrib/tabler-icons/edit.svg +0 -0
  127. {open_swarm-0.1.1743371228 → open_swarm-0.1.1743372974}/src/swarm/static/contrib/tabler-icons/filled/carambola.svg +0 -0
  128. {open_swarm-0.1.1743371228 → open_swarm-0.1.1743372974}/src/swarm/static/contrib/tabler-icons/filled/paint.svg +0 -0
  129. {open_swarm-0.1.1743371228 → open_swarm-0.1.1743372974}/src/swarm/static/contrib/tabler-icons/headset.svg +0 -0
  130. {open_swarm-0.1.1743371228 → open_swarm-0.1.1743372974}/src/swarm/static/contrib/tabler-icons/layout-sidebar-left-collapse.svg +0 -0
  131. {open_swarm-0.1.1743371228 → open_swarm-0.1.1743372974}/src/swarm/static/contrib/tabler-icons/layout-sidebar-left-expand.svg +0 -0
  132. {open_swarm-0.1.1743371228 → open_swarm-0.1.1743372974}/src/swarm/static/contrib/tabler-icons/layout-sidebar-right-collapse.svg +0 -0
  133. {open_swarm-0.1.1743371228 → open_swarm-0.1.1743372974}/src/swarm/static/contrib/tabler-icons/layout-sidebar-right-expand.svg +0 -0
  134. {open_swarm-0.1.1743371228 → open_swarm-0.1.1743372974}/src/swarm/static/contrib/tabler-icons/message-chatbot.svg +0 -0
  135. {open_swarm-0.1.1743371228 → open_swarm-0.1.1743372974}/src/swarm/static/contrib/tabler-icons/message-star.svg +0 -0
  136. {open_swarm-0.1.1743371228 → open_swarm-0.1.1743372974}/src/swarm/static/contrib/tabler-icons/message-x.svg +0 -0
  137. {open_swarm-0.1.1743371228 → open_swarm-0.1.1743372974}/src/swarm/static/contrib/tabler-icons/message.svg +0 -0
  138. {open_swarm-0.1.1743371228 → open_swarm-0.1.1743372974}/src/swarm/static/contrib/tabler-icons/paperclip.svg +0 -0
  139. {open_swarm-0.1.1743371228 → open_swarm-0.1.1743372974}/src/swarm/static/contrib/tabler-icons/playlist-add.svg +0 -0
  140. {open_swarm-0.1.1743371228 → open_swarm-0.1.1743372974}/src/swarm/static/contrib/tabler-icons/robot.svg +0 -0
  141. {open_swarm-0.1.1743371228 → open_swarm-0.1.1743372974}/src/swarm/static/contrib/tabler-icons/search.svg +0 -0
  142. {open_swarm-0.1.1743371228 → open_swarm-0.1.1743372974}/src/swarm/static/contrib/tabler-icons/settings.svg +0 -0
  143. {open_swarm-0.1.1743371228 → open_swarm-0.1.1743372974}/src/swarm/static/contrib/tabler-icons/thumb-down.svg +0 -0
  144. {open_swarm-0.1.1743371228 → open_swarm-0.1.1743372974}/src/swarm/static/contrib/tabler-icons/thumb-up.svg +0 -0
  145. {open_swarm-0.1.1743371228 → open_swarm-0.1.1743372974}/src/swarm/static/css/dropdown.css +0 -0
  146. {open_swarm-0.1.1743371228 → open_swarm-0.1.1743372974}/src/swarm/static/htmx/htmx.min.js +0 -0
  147. {open_swarm-0.1.1743371228 → open_swarm-0.1.1743372974}/src/swarm/static/js/dropdown.js +0 -0
  148. {open_swarm-0.1.1743371228 → open_swarm-0.1.1743372974}/src/swarm/static/rest_mode/css/base.css +0 -0
  149. {open_swarm-0.1.1743371228 → open_swarm-0.1.1743372974}/src/swarm/static/rest_mode/css/chat-history.css +0 -0
  150. {open_swarm-0.1.1743371228 → open_swarm-0.1.1743372974}/src/swarm/static/rest_mode/css/chat.css +0 -0
  151. {open_swarm-0.1.1743371228 → open_swarm-0.1.1743372974}/src/swarm/static/rest_mode/css/chatbot.css +0 -0
  152. {open_swarm-0.1.1743371228 → open_swarm-0.1.1743372974}/src/swarm/static/rest_mode/css/chatgpt.css +0 -0
  153. {open_swarm-0.1.1743371228 → open_swarm-0.1.1743372974}/src/swarm/static/rest_mode/css/colors/corporate.css +0 -0
  154. {open_swarm-0.1.1743371228 → open_swarm-0.1.1743372974}/src/swarm/static/rest_mode/css/colors/pastel.css +0 -0
  155. {open_swarm-0.1.1743371228 → open_swarm-0.1.1743372974}/src/swarm/static/rest_mode/css/colors/tropical.css +0 -0
  156. {open_swarm-0.1.1743371228 → open_swarm-0.1.1743372974}/src/swarm/static/rest_mode/css/general.css +0 -0
  157. {open_swarm-0.1.1743371228 → open_swarm-0.1.1743372974}/src/swarm/static/rest_mode/css/layout.css +0 -0
  158. {open_swarm-0.1.1743371228 → open_swarm-0.1.1743372974}/src/swarm/static/rest_mode/css/layouts/messenger-layout.css +0 -0
  159. {open_swarm-0.1.1743371228 → open_swarm-0.1.1743372974}/src/swarm/static/rest_mode/css/layouts/minimalist-layout.css +0 -0
  160. {open_swarm-0.1.1743371228 → open_swarm-0.1.1743372974}/src/swarm/static/rest_mode/css/layouts/mobile-layout.css +0 -0
  161. {open_swarm-0.1.1743371228 → open_swarm-0.1.1743372974}/src/swarm/static/rest_mode/css/messages.css +0 -0
  162. {open_swarm-0.1.1743371228 → open_swarm-0.1.1743372974}/src/swarm/static/rest_mode/css/messenger.css +0 -0
  163. {open_swarm-0.1.1743371228 → open_swarm-0.1.1743372974}/src/swarm/static/rest_mode/css/settings.css +0 -0
  164. {open_swarm-0.1.1743371228 → open_swarm-0.1.1743372974}/src/swarm/static/rest_mode/css/simple.css +0 -0
  165. {open_swarm-0.1.1743371228 → open_swarm-0.1.1743372974}/src/swarm/static/rest_mode/css/slack.css +0 -0
  166. {open_swarm-0.1.1743371228 → open_swarm-0.1.1743372974}/src/swarm/static/rest_mode/css/style.css +0 -0
  167. {open_swarm-0.1.1743371228 → open_swarm-0.1.1743372974}/src/swarm/static/rest_mode/css/theme.css +0 -0
  168. {open_swarm-0.1.1743371228 → open_swarm-0.1.1743372974}/src/swarm/static/rest_mode/css/toast.css +0 -0
  169. {open_swarm-0.1.1743371228 → open_swarm-0.1.1743372974}/src/swarm/static/rest_mode/js/auth.js +0 -0
  170. {open_swarm-0.1.1743371228 → open_swarm-0.1.1743372974}/src/swarm/static/rest_mode/js/blueprint.js +0 -0
  171. {open_swarm-0.1.1743371228 → open_swarm-0.1.1743372974}/src/swarm/static/rest_mode/js/blueprintUtils.js +0 -0
  172. {open_swarm-0.1.1743371228 → open_swarm-0.1.1743372974}/src/swarm/static/rest_mode/js/chatLogic.js +0 -0
  173. {open_swarm-0.1.1743371228 → open_swarm-0.1.1743372974}/src/swarm/static/rest_mode/js/debug.js +0 -0
  174. {open_swarm-0.1.1743371228 → open_swarm-0.1.1743372974}/src/swarm/static/rest_mode/js/events.js +0 -0
  175. {open_swarm-0.1.1743371228 → open_swarm-0.1.1743372974}/src/swarm/static/rest_mode/js/main.js +0 -0
  176. {open_swarm-0.1.1743371228 → open_swarm-0.1.1743372974}/src/swarm/static/rest_mode/js/messages.js +0 -0
  177. {open_swarm-0.1.1743371228 → open_swarm-0.1.1743372974}/src/swarm/static/rest_mode/js/messengerLogic.js +0 -0
  178. {open_swarm-0.1.1743371228 → open_swarm-0.1.1743372974}/src/swarm/static/rest_mode/js/modules/apiService.js +0 -0
  179. {open_swarm-0.1.1743371228 → open_swarm-0.1.1743372974}/src/swarm/static/rest_mode/js/modules/blueprintManager.js +0 -0
  180. {open_swarm-0.1.1743371228 → open_swarm-0.1.1743372974}/src/swarm/static/rest_mode/js/modules/chatHistory.js +0 -0
  181. {open_swarm-0.1.1743371228 → open_swarm-0.1.1743372974}/src/swarm/static/rest_mode/js/modules/debugLogger.js +0 -0
  182. {open_swarm-0.1.1743371228 → open_swarm-0.1.1743372974}/src/swarm/static/rest_mode/js/modules/eventHandlers.js +0 -0
  183. {open_swarm-0.1.1743371228 → open_swarm-0.1.1743372974}/src/swarm/static/rest_mode/js/modules/messageProcessor.js +0 -0
  184. {open_swarm-0.1.1743371228 → open_swarm-0.1.1743372974}/src/swarm/static/rest_mode/js/modules/state.js +0 -0
  185. {open_swarm-0.1.1743371228 → open_swarm-0.1.1743372974}/src/swarm/static/rest_mode/js/modules/userInteractions.js +0 -0
  186. {open_swarm-0.1.1743371228 → open_swarm-0.1.1743372974}/src/swarm/static/rest_mode/js/modules/validation.js +0 -0
  187. {open_swarm-0.1.1743371228 → open_swarm-0.1.1743372974}/src/swarm/static/rest_mode/js/rendering.js +0 -0
  188. {open_swarm-0.1.1743371228 → open_swarm-0.1.1743372974}/src/swarm/static/rest_mode/js/settings.js +0 -0
  189. {open_swarm-0.1.1743371228 → open_swarm-0.1.1743372974}/src/swarm/static/rest_mode/js/sidebar.js +0 -0
  190. {open_swarm-0.1.1743371228 → open_swarm-0.1.1743372974}/src/swarm/static/rest_mode/js/simpleLogic.js +0 -0
  191. {open_swarm-0.1.1743371228 → open_swarm-0.1.1743372974}/src/swarm/static/rest_mode/js/slackLogic.js +0 -0
  192. {open_swarm-0.1.1743371228 → open_swarm-0.1.1743372974}/src/swarm/static/rest_mode/js/splash.js +0 -0
  193. {open_swarm-0.1.1743371228 → open_swarm-0.1.1743372974}/src/swarm/static/rest_mode/js/theme.js +0 -0
  194. {open_swarm-0.1.1743371228 → open_swarm-0.1.1743372974}/src/swarm/static/rest_mode/js/toast.js +0 -0
  195. {open_swarm-0.1.1743371228 → open_swarm-0.1.1743372974}/src/swarm/static/rest_mode/js/ui.js +0 -0
  196. {open_swarm-0.1.1743371228 → open_swarm-0.1.1743372974}/src/swarm/static/rest_mode/js/validation.js +0 -0
  197. {open_swarm-0.1.1743371228 → open_swarm-0.1.1743372974}/src/swarm/static/rest_mode/svg/animated_spinner.svg +0 -0
  198. {open_swarm-0.1.1743371228 → open_swarm-0.1.1743372974}/src/swarm/static/rest_mode/svg/arrow_down.svg +0 -0
  199. {open_swarm-0.1.1743371228 → open_swarm-0.1.1743372974}/src/swarm/static/rest_mode/svg/arrow_left.svg +0 -0
  200. {open_swarm-0.1.1743371228 → open_swarm-0.1.1743372974}/src/swarm/static/rest_mode/svg/arrow_right.svg +0 -0
  201. {open_swarm-0.1.1743371228 → open_swarm-0.1.1743372974}/src/swarm/static/rest_mode/svg/arrow_up.svg +0 -0
  202. {open_swarm-0.1.1743371228 → open_swarm-0.1.1743372974}/src/swarm/static/rest_mode/svg/attach.svg +0 -0
  203. {open_swarm-0.1.1743371228 → open_swarm-0.1.1743372974}/src/swarm/static/rest_mode/svg/avatar.svg +0 -0
  204. {open_swarm-0.1.1743371228 → open_swarm-0.1.1743372974}/src/swarm/static/rest_mode/svg/canvas.svg +0 -0
  205. {open_swarm-0.1.1743371228 → open_swarm-0.1.1743372974}/src/swarm/static/rest_mode/svg/chat_history.svg +0 -0
  206. {open_swarm-0.1.1743371228 → open_swarm-0.1.1743372974}/src/swarm/static/rest_mode/svg/close.svg +0 -0
  207. {open_swarm-0.1.1743371228 → open_swarm-0.1.1743372974}/src/swarm/static/rest_mode/svg/copy.svg +0 -0
  208. {open_swarm-0.1.1743371228 → open_swarm-0.1.1743372974}/src/swarm/static/rest_mode/svg/dark_mode.svg +0 -0
  209. {open_swarm-0.1.1743371228 → open_swarm-0.1.1743372974}/src/swarm/static/rest_mode/svg/edit.svg +0 -0
  210. {open_swarm-0.1.1743371228 → open_swarm-0.1.1743372974}/src/swarm/static/rest_mode/svg/layout.svg +0 -0
  211. {open_swarm-0.1.1743371228 → open_swarm-0.1.1743372974}/src/swarm/static/rest_mode/svg/logo.svg +0 -0
  212. {open_swarm-0.1.1743371228 → open_swarm-0.1.1743372974}/src/swarm/static/rest_mode/svg/logout.svg +0 -0
  213. {open_swarm-0.1.1743371228 → open_swarm-0.1.1743372974}/src/swarm/static/rest_mode/svg/mobile.svg +0 -0
  214. {open_swarm-0.1.1743371228 → open_swarm-0.1.1743372974}/src/swarm/static/rest_mode/svg/new_chat.svg +0 -0
  215. {open_swarm-0.1.1743371228 → open_swarm-0.1.1743372974}/src/swarm/static/rest_mode/svg/not_visible.svg +0 -0
  216. {open_swarm-0.1.1743371228 → open_swarm-0.1.1743372974}/src/swarm/static/rest_mode/svg/plus.svg +0 -0
  217. {open_swarm-0.1.1743371228 → open_swarm-0.1.1743372974}/src/swarm/static/rest_mode/svg/run_code.svg +0 -0
  218. {open_swarm-0.1.1743371228 → open_swarm-0.1.1743372974}/src/swarm/static/rest_mode/svg/save.svg +0 -0
  219. {open_swarm-0.1.1743371228 → open_swarm-0.1.1743372974}/src/swarm/static/rest_mode/svg/search.svg +0 -0
  220. {open_swarm-0.1.1743371228 → open_swarm-0.1.1743372974}/src/swarm/static/rest_mode/svg/settings.svg +0 -0
  221. {open_swarm-0.1.1743371228 → open_swarm-0.1.1743372974}/src/swarm/static/rest_mode/svg/speaker.svg +0 -0
  222. {open_swarm-0.1.1743371228 → open_swarm-0.1.1743372974}/src/swarm/static/rest_mode/svg/stop.svg +0 -0
  223. {open_swarm-0.1.1743371228 → open_swarm-0.1.1743372974}/src/swarm/static/rest_mode/svg/thumbs_down.svg +0 -0
  224. {open_swarm-0.1.1743371228 → open_swarm-0.1.1743372974}/src/swarm/static/rest_mode/svg/thumbs_up.svg +0 -0
  225. {open_swarm-0.1.1743371228 → open_swarm-0.1.1743372974}/src/swarm/static/rest_mode/svg/toggle_off.svg +0 -0
  226. {open_swarm-0.1.1743371228 → open_swarm-0.1.1743372974}/src/swarm/static/rest_mode/svg/toggle_on.svg +0 -0
  227. {open_swarm-0.1.1743371228 → open_swarm-0.1.1743372974}/src/swarm/static/rest_mode/svg/trash.svg +0 -0
  228. {open_swarm-0.1.1743371228 → open_swarm-0.1.1743372974}/src/swarm/static/rest_mode/svg/undo.svg +0 -0
  229. {open_swarm-0.1.1743371228 → open_swarm-0.1.1743372974}/src/swarm/static/rest_mode/svg/visible.svg +0 -0
  230. {open_swarm-0.1.1743371228 → open_swarm-0.1.1743372974}/src/swarm/static/rest_mode/svg/voice.svg +0 -0
  231. {open_swarm-0.1.1743371228 → open_swarm-0.1.1743372974}/src/swarm/templates/account/login.html +0 -0
  232. {open_swarm-0.1.1743371228 → open_swarm-0.1.1743372974}/src/swarm/templates/account/signup.html +0 -0
  233. {open_swarm-0.1.1743371228 → open_swarm-0.1.1743372974}/src/swarm/templates/base.html +0 -0
  234. {open_swarm-0.1.1743371228 → open_swarm-0.1.1743372974}/src/swarm/templates/chat.html +0 -0
  235. {open_swarm-0.1.1743371228 → open_swarm-0.1.1743372974}/src/swarm/templates/index.html +0 -0
  236. {open_swarm-0.1.1743371228 → open_swarm-0.1.1743372974}/src/swarm/templates/rest_mode/components/chat_sidebar.html +0 -0
  237. {open_swarm-0.1.1743371228 → open_swarm-0.1.1743372974}/src/swarm/templates/rest_mode/components/header.html +0 -0
  238. {open_swarm-0.1.1743371228 → open_swarm-0.1.1743372974}/src/swarm/templates/rest_mode/components/main_chat_pane.html +0 -0
  239. {open_swarm-0.1.1743371228 → open_swarm-0.1.1743372974}/src/swarm/templates/rest_mode/components/settings_dialog.html +0 -0
  240. {open_swarm-0.1.1743371228 → open_swarm-0.1.1743372974}/src/swarm/templates/rest_mode/components/splash_screen.html +0 -0
  241. {open_swarm-0.1.1743371228 → open_swarm-0.1.1743372974}/src/swarm/templates/rest_mode/components/top_bar.html +0 -0
  242. {open_swarm-0.1.1743371228 → open_swarm-0.1.1743372974}/src/swarm/templates/rest_mode/message_ui.html +0 -0
  243. {open_swarm-0.1.1743371228 → open_swarm-0.1.1743372974}/src/swarm/templates/rest_mode/slackbot.html +0 -0
  244. {open_swarm-0.1.1743371228 → open_swarm-0.1.1743372974}/src/swarm/templates/simple_blueprint_page.html +0 -0
  245. {open_swarm-0.1.1743371228 → open_swarm-0.1.1743372974}/src/swarm/templates/websocket_partials/final_system_message.html +0 -0
  246. {open_swarm-0.1.1743371228 → open_swarm-0.1.1743372974}/src/swarm/templates/websocket_partials/system_message.html +0 -0
  247. {open_swarm-0.1.1743371228 → open_swarm-0.1.1743372974}/src/swarm/templates/websocket_partials/user_message.html +0 -0
  248. {open_swarm-0.1.1743371228 → open_swarm-0.1.1743372974}/src/swarm/tool_executor.py +0 -0
  249. {open_swarm-0.1.1743371228 → open_swarm-0.1.1743372974}/src/swarm/urls.py +0 -0
  250. {open_swarm-0.1.1743371228 → open_swarm-0.1.1743372974}/src/swarm/util.py +0 -0
  251. {open_swarm-0.1.1743371228 → open_swarm-0.1.1743372974}/src/swarm/utils/color_utils.py +0 -0
  252. {open_swarm-0.1.1743371228 → open_swarm-0.1.1743372974}/src/swarm/utils/context_utils.py +0 -0
  253. {open_swarm-0.1.1743371228 → open_swarm-0.1.1743372974}/src/swarm/utils/general_utils.py +0 -0
  254. {open_swarm-0.1.1743371228 → open_swarm-0.1.1743372974}/src/swarm/utils/log_utils.py +0 -0
  255. {open_swarm-0.1.1743371228 → open_swarm-0.1.1743372974}/src/swarm/utils/logger.py +0 -0
  256. {open_swarm-0.1.1743371228 → open_swarm-0.1.1743372974}/src/swarm/utils/logger_setup.py +0 -0
  257. {open_swarm-0.1.1743371228 → open_swarm-0.1.1743372974}/src/swarm/utils/message_sequence.py +0 -0
  258. {open_swarm-0.1.1743371228 → open_swarm-0.1.1743372974}/src/swarm/utils/message_utils.py +0 -0
  259. {open_swarm-0.1.1743371228 → open_swarm-0.1.1743372974}/src/swarm/utils/redact.py +0 -0
  260. {open_swarm-0.1.1743371228 → open_swarm-0.1.1743372974}/src/swarm/views/__init__.py +0 -0
  261. {open_swarm-0.1.1743371228 → open_swarm-0.1.1743372974}/src/swarm/views/api_views.py +0 -0
  262. {open_swarm-0.1.1743371228 → open_swarm-0.1.1743372974}/src/swarm/views/chat_views.py +0 -0
  263. {open_swarm-0.1.1743371228 → open_swarm-0.1.1743372974}/src/swarm/views/core_views.py +0 -0
  264. {open_swarm-0.1.1743371228 → open_swarm-0.1.1743372974}/src/swarm/views/message_views.py +0 -0
  265. {open_swarm-0.1.1743371228 → open_swarm-0.1.1743372974}/src/swarm/views/model_views.py +0 -0
  266. {open_swarm-0.1.1743371228 → open_swarm-0.1.1743372974}/src/swarm/views/utils.py +0 -0
  267. {open_swarm-0.1.1743371228 → open_swarm-0.1.1743372974}/src/swarm/views/web_views.py +0 -0
  268. {open_swarm-0.1.1743371228 → open_swarm-0.1.1743372974}/src/swarm/wsgi.py +0 -0
  269. {open_swarm-0.1.1743371228 → open_swarm-0.1.1743372974}/tests/__init__.py +0 -0
  270. {open_swarm-0.1.1743371228 → open_swarm-0.1.1743372974}/tests/api/conftest.py +0 -0
  271. {open_swarm-0.1.1743371228 → open_swarm-0.1.1743372974}/tests/api/test_chat_completions_auth_async.py +0 -0
  272. {open_swarm-0.1.1743371228 → open_swarm-0.1.1743372974}/tests/api/test_chat_completions_failing_async.py +0 -0
  273. {open_swarm-0.1.1743371228 → open_swarm-0.1.1743372974}/tests/api/test_chat_completions_validation_async.py +0 -0
  274. {open_swarm-0.1.1743371228 → open_swarm-0.1.1743372974}/tests/blueprints/test_burnt_noodles.py +0 -0
  275. {open_swarm-0.1.1743371228 → open_swarm-0.1.1743372974}/tests/blueprints/test_chatbot.py +0 -0
  276. {open_swarm-0.1.1743371228 → open_swarm-0.1.1743372974}/tests/blueprints/test_digitalbutlers.py +0 -0
  277. {open_swarm-0.1.1743371228 → open_swarm-0.1.1743372974}/tests/blueprints/test_dilbot_universe.py +0 -0
  278. {open_swarm-0.1.1743371228 → open_swarm-0.1.1743372974}/tests/blueprints/test_divine_code.py +0 -0
  279. {open_swarm-0.1.1743371228 → open_swarm-0.1.1743372974}/tests/blueprints/test_family_ties.py +0 -0
  280. {open_swarm-0.1.1743371228 → open_swarm-0.1.1743372974}/tests/blueprints/test_gaggle.py +0 -0
  281. {open_swarm-0.1.1743371228 → open_swarm-0.1.1743372974}/tests/blueprints/test_gotchaman.py +0 -0
  282. {open_swarm-0.1.1743371228 → open_swarm-0.1.1743372974}/tests/blueprints/test_mcp_demo.py +0 -0
  283. {open_swarm-0.1.1743371228 → open_swarm-0.1.1743372974}/tests/blueprints/test_mission_improbable.py +0 -0
  284. {open_swarm-0.1.1743371228 → open_swarm-0.1.1743372974}/tests/blueprints/test_monkai_magic.py +0 -0
  285. {open_swarm-0.1.1743371228 → open_swarm-0.1.1743372974}/tests/blueprints/test_nebula_shellz.py +0 -0
  286. {open_swarm-0.1.1743371228 → open_swarm-0.1.1743372974}/tests/blueprints/test_omniplex.py +0 -0
  287. {open_swarm-0.1.1743371228 → open_swarm-0.1.1743372974}/tests/blueprints/test_suggestion.py +0 -0
  288. {open_swarm-0.1.1743371228 → open_swarm-0.1.1743372974}/tests/blueprints/test_unapologetic_press.py +0 -0
  289. {open_swarm-0.1.1743371228 → open_swarm-0.1.1743372974}/tests/blueprints/test_whiskeytangofoxtrot.py +0 -0
  290. {open_swarm-0.1.1743371228 → open_swarm-0.1.1743372974}/tests/cli/test_list_blueprints.py +0 -0
  291. {open_swarm-0.1.1743371228 → open_swarm-0.1.1743372974}/tests/conftest.py +0 -0
  292. {open_swarm-0.1.1743371228 → open_swarm-0.1.1743372974}/tests/swarm_config.json +0 -0
  293. {open_swarm-0.1.1743371228 → open_swarm-0.1.1743372974}/tests/system/test_burnt_noodles.sh +0 -0
  294. {open_swarm-0.1.1743371228 → open_swarm-0.1.1743372974}/tests/system/test_chucks_angels.sh +0 -0
  295. {open_swarm-0.1.1743371228 → open_swarm-0.1.1743372974}/tests/system/test_digitalbutlers.sh +0 -0
  296. {open_swarm-0.1.1743371228 → open_swarm-0.1.1743372974}/tests/system/test_dilbot_universe.sh +0 -0
  297. {open_swarm-0.1.1743371228 → open_swarm-0.1.1743372974}/tests/system/test_divine_code.sh +0 -0
  298. {open_swarm-0.1.1743371228 → open_swarm-0.1.1743372974}/tests/system/test_django_chat.sh +0 -0
  299. {open_swarm-0.1.1743371228 → open_swarm-0.1.1743372974}/tests/system/test_echocraft.sh +0 -0
  300. {open_swarm-0.1.1743371228 → open_swarm-0.1.1743372974}/tests/system/test_family_ties.sh +0 -0
  301. {open_swarm-0.1.1743371228 → open_swarm-0.1.1743372974}/tests/system/test_flock.sh +0 -0
  302. {open_swarm-0.1.1743371228 → open_swarm-0.1.1743372974}/tests/system/test_gaggle.sh +0 -0
  303. {open_swarm-0.1.1743371228 → open_swarm-0.1.1743372974}/tests/system/test_gotchaman.sh +0 -0
  304. {open_swarm-0.1.1743371228 → open_swarm-0.1.1743372974}/tests/system/test_monkai-magic.sh +0 -0
  305. {open_swarm-0.1.1743371228 → open_swarm-0.1.1743372974}/tests/system/test_nebula_shellz.sh +0 -0
  306. {open_swarm-0.1.1743371228 → open_swarm-0.1.1743372974}/tests/system/test_omniplex.sh +0 -0
  307. {open_swarm-0.1.1743371228 → open_swarm-0.1.1743372974}/tests/system/test_rue-code.sh +0 -0
  308. {open_swarm-0.1.1743371228 → open_swarm-0.1.1743372974}/tests/system/test_suggestion.sh +0 -0
  309. {open_swarm-0.1.1743371228 → open_swarm-0.1.1743372974}/tests/system/test_unapologetic_press.sh +0 -0
  310. {open_swarm-0.1.1743371228 → open_swarm-0.1.1743372974}/tests/system/test_university.sh +0 -0
  311. {open_swarm-0.1.1743371228 → open_swarm-0.1.1743372974}/tests/system/test_whiskeytango_foxtrot.sh +0 -0
  312. {open_swarm-0.1.1743371228 → open_swarm-0.1.1743372974}/tests/test_blueprint_loading.py +0 -0
  313. {open_swarm-0.1.1743371228 → open_swarm-0.1.1743372974}/tests/test_cli_mode_selection.py +0 -0
  314. {open_swarm-0.1.1743371228 → open_swarm-0.1.1743372974}/tests/test_core_filter_duplicate_system_messages.py +0 -0
  315. {open_swarm-0.1.1743371228 → open_swarm-0.1.1743372974}/tests/test_core_filter_messages.py +0 -0
  316. {open_swarm-0.1.1743371228 → open_swarm-0.1.1743372974}/tests/test_core_truncate_message_history.py +0 -0
  317. {open_swarm-0.1.1743371228 → open_swarm-0.1.1743372974}/tests/test_core_update_null_content.py +0 -0
  318. {open_swarm-0.1.1743371228 → open_swarm-0.1.1743372974}/tests/test_dummy.py +0 -0
  319. {open_swarm-0.1.1743371228 → open_swarm-0.1.1743372974}/tests/test_truncate_message_history.py +0 -0
  320. {open_swarm-0.1.1743371228 → open_swarm-0.1.1743372974}/tests/unit/blueprints/rue_code/test_rue_code_tools.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: open-swarm
3
- Version: 0.1.1743371228
3
+ Version: 0.1.1743372974
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`).
@@ -17,7 +17,7 @@ Open Swarm can be used in two primary ways:
17
17
 
18
18
  * **Agents:** Individual AI units performing specific tasks, powered by LLMs (like GPT-4, Claude, etc.). Built using the `openai-agents` SDK.
19
19
  * **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).
20
- * **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.
20
+ * **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.
21
21
  * **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/`.
22
22
  * **`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/`).
23
23
  * **`swarm-api`:** A launcher for the Django/DRF backend that exposes installed blueprints via an OpenAI-compatible REST API (`/v1/models`, `/v1/chat/completions`).
@@ -4,7 +4,7 @@ build-backend = "hatchling.build"
4
4
 
5
5
  [project]
6
6
  name = "open-swarm"
7
- version = "0.1.1743371228"
7
+ version = "0.1.1743372974"
8
8
  description = "Open Swarm: Orchestrating AI Agent Swarms with Django"
9
9
  readme = "README.md"
10
10
  requires-python = ">=3.10"
@@ -139,6 +139,9 @@ ignore_missing_imports = true
139
139
  [tool.pytest.ini_options]
140
140
  DJANGO_SETTINGS_MODULE = "swarm.settings"
141
141
  python_files = ["tests.py", "test_*.py", "*_tests.py"]
142
+ env = [
143
+ "DJANGO_ALLOW_ASYNC_UNSAFE=true",
144
+ ]
142
145
  testpaths = ["tests"]
143
146
  asyncio_mode = "auto"
144
147
  asyncio_default_fixture_loop_scope = "function"
@@ -0,0 +1,71 @@
1
+
2
+ # --- Content for src/swarm/blueprints/echocraft/blueprint_echocraft.py ---
3
+ import logging
4
+ from typing import List, Dict, Any, AsyncGenerator
5
+ import uuid # Import uuid to generate IDs
6
+ import time # Import time for timestamp
7
+
8
+ from swarm.extensions.blueprint.blueprint_base import BlueprintBase
9
+
10
+ logger = logging.getLogger(__name__)
11
+
12
+ class EchoCraftBlueprint(BlueprintBase):
13
+ """
14
+ A simple blueprint that echoes the last user message.
15
+ Used for testing and demonstrating basic blueprint structure.
16
+ """
17
+
18
+ # No specific __init__ needed beyond the base class unless adding more params
19
+ # def __init__(self, blueprint_id: str, **kwargs):
20
+ # super().__init__(blueprint_id=blueprint_id, **kwargs)
21
+ # logger.info(f"EchoCraftBlueprint '{self.blueprint_id}' initialized.")
22
+
23
+ async def run(self, messages: List[Dict[str, Any]], **kwargs: Any) -> AsyncGenerator[Dict[str, Any], None]:
24
+ """
25
+ Echoes the content of the last message with role 'user'.
26
+ Yields a final message in OpenAI ChatCompletion format.
27
+ """
28
+ logger.info(f"EchoCraftBlueprint run called with {len(messages)} messages.")
29
+
30
+ last_user_message_content = "No user message found."
31
+ for msg in reversed(messages):
32
+ if msg.get("role") == "user":
33
+ last_user_message_content = msg.get("content", "(empty content)")
34
+ logger.debug(f"Found last user message: {last_user_message_content}")
35
+ break
36
+
37
+ echo_content = f"Echo: {last_user_message_content}"
38
+ logger.info(f"EchoCraftBlueprint yielding: {echo_content}")
39
+
40
+ # --- Format the final output as an OpenAI ChatCompletion object ---
41
+ completion_id = f"chatcmpl-echo-{uuid.uuid4()}"
42
+ created_timestamp = int(time.time())
43
+
44
+ final_message_chunk = {
45
+ "id": completion_id,
46
+ "object": "chat.completion",
47
+ "created": created_timestamp,
48
+ "model": self.llm_profile_name, # Use profile name as model identifier
49
+ "choices": [
50
+ {
51
+ "index": 0,
52
+ "message": {
53
+ "role": "assistant",
54
+ "content": echo_content,
55
+ },
56
+ "finish_reason": "stop",
57
+ "logprobs": None, # Add null logprobs if needed
58
+ }
59
+ ],
60
+ # Add usage stats if desired/possible
61
+ # "usage": {
62
+ # "prompt_tokens": 0,
63
+ # "completion_tokens": 0,
64
+ # "total_tokens": 0
65
+ # }
66
+ }
67
+ yield final_message_chunk
68
+ # --- End formatting change ---
69
+
70
+ logger.info("EchoCraftBlueprint run finished.")
71
+
@@ -0,0 +1,111 @@
1
+
2
+ # --- Content for src/swarm/extensions/blueprint/blueprint_base.py ---
3
+ import logging
4
+ import json
5
+ from abc import ABC, abstractmethod
6
+ from typing import Dict, Any, Optional, List, AsyncGenerator
7
+ from pathlib import Path
8
+ from django.apps import apps # Import Django apps registry
9
+
10
+ # Keep the function import
11
+ from swarm.extensions.config.config_loader import get_profile_from_config
12
+
13
+ logger = logging.getLogger(__name__)
14
+
15
+ class BlueprintBase(ABC):
16
+ """
17
+ Abstract base class for all Swarm blueprints.
18
+
19
+ Defines the core interface for blueprint initialization and execution.
20
+ """
21
+ def __init__(self, blueprint_id: str, config_path: Optional[Path] = None):
22
+ """
23
+ Initializes the blueprint.
24
+
25
+ Args:
26
+ blueprint_id: A unique identifier for this blueprint instance.
27
+ config_path: Optional path to a specific swarm_config.json file.
28
+ If None, the standard search logic will be used.
29
+ """
30
+ if not blueprint_id:
31
+ raise ValueError("blueprint_id cannot be empty or None") # Add validation
32
+ self.blueprint_id = blueprint_id
33
+ self.config_path = config_path # Note: config_path is currently unused if we rely on AppConfig
34
+ self._config: Optional[Dict[str, Any]] = None
35
+ self._llm_profile_name: Optional[str] = None
36
+ self._llm_profile_data: Optional[Dict[str, Any]] = None
37
+ self._markdown_output: bool = True # Default
38
+
39
+ logger.info(f"Initializing blueprint '{self.blueprint_id}' (Type: {self.__class__.__name__})")
40
+ self._load_and_process_config()
41
+
42
+ def _load_and_process_config(self):
43
+ """Loads the main Swarm config and extracts relevant settings."""
44
+ try:
45
+ # --- Get config from the AppConfig instance ---
46
+ app_config_instance = apps.get_app_config('swarm')
47
+ # Assuming the loaded config is stored in an attribute named 'config'
48
+ # Adjust 'config' if your AppConfig uses a different attribute name
49
+ if not hasattr(app_config_instance, 'config') or not app_config_instance.config:
50
+ logger.error("Swarm configuration not found on AppConfig instance. Was ready() called?")
51
+ raise ValueError("Swarm configuration unavailable via AppConfig.")
52
+ self._config = app_config_instance.config
53
+ # --- End change ---
54
+
55
+ logger.debug(f"Blueprint '{self.blueprint_id}' using loaded Swarm config.")
56
+
57
+ # Determine LLM profile
58
+ self._llm_profile_name = self._config.get("settings", {}).get("default_llm_profile", "default")
59
+ logger.debug(f"Attempting to use LLM profile: '{self._llm_profile_name}'")
60
+
61
+ # Get substituted profile data
62
+ self._llm_profile_data = get_profile_from_config(self._config, self._llm_profile_name)
63
+ logger.info(f"Successfully loaded LLM profile '{self._llm_profile_name}'. Provider: {self._llm_profile_data.get('provider')}")
64
+
65
+ # Get markdown setting
66
+ blueprint_specific_settings = self._config.get("blueprints", {}).get(self.blueprint_id, {})
67
+ global_markdown_setting = self._config.get("settings", {}).get("default_markdown_output", True)
68
+ self._markdown_output = blueprint_specific_settings.get("markdown_output", global_markdown_setting)
69
+ logger.debug(f"Markdown output for '{self.blueprint_id}': {self._markdown_output}")
70
+
71
+ except ValueError as e:
72
+ logger.error(f"Configuration error for blueprint '{self.blueprint_id}': {e}", exc_info=True)
73
+ raise
74
+ except Exception as e:
75
+ logger.error(f"Unexpected error loading config for blueprint '{self.blueprint_id}': {e}", exc_info=True)
76
+ raise
77
+
78
+ @property
79
+ def config(self) -> Dict[str, Any]:
80
+ """Returns the loaded and processed Swarm configuration."""
81
+ if self._config is None:
82
+ raise RuntimeError("Configuration accessed before initialization or after failure.")
83
+ return self._config
84
+
85
+ @property
86
+ def llm_profile(self) -> Dict[str, Any]:
87
+ """Returns the loaded and processed LLM profile data for this blueprint."""
88
+ if self._llm_profile_data is None:
89
+ raise RuntimeError("LLM profile accessed before initialization or after failure.")
90
+ return self._llm_profile_data
91
+
92
+ @property
93
+ def llm_profile_name(self) -> str:
94
+ """Returns the name of the LLM profile being used."""
95
+ if self._llm_profile_name is None:
96
+ raise RuntimeError("LLM profile name accessed before initialization or after failure.")
97
+ return self._llm_profile_name
98
+
99
+ @property
100
+ def should_output_markdown(self) -> bool:
101
+ """Returns whether the blueprint should format output as Markdown."""
102
+ return self._markdown_output
103
+
104
+ @abstractmethod
105
+ async def run(self, messages: List[Dict[str, Any]], **kwargs: Any) -> AsyncGenerator[Dict[str, Any], None]:
106
+ """
107
+ The main execution method for the blueprint.
108
+ """
109
+ raise NotImplementedError("Subclasses must implement the 'run' method.")
110
+ yield {}
111
+
@@ -0,0 +1,76 @@
1
+
2
+ # --- Content for tests/blueprints/test_echocraft.py ---
3
+ import pytest
4
+ from typing import List, Dict, Any
5
+ import asyncio
6
+ from unittest.mock import patch, MagicMock # Import mock tools
7
+
8
+ from swarm.blueprints.echocraft.blueprint_echocraft import EchoCraftBlueprint
9
+
10
+ # Helper to collect results from async generator
11
+ async def collect_results(agen):
12
+ return [item async for item in agen]
13
+
14
+ # Fixture to provide a mock app_config with a basic config dict
15
+ @pytest.fixture
16
+ def mock_app_config(mocker):
17
+ mock_instance = MagicMock()
18
+ mock_instance.config = {
19
+ "llm": {"default": {"provider": "mock", "model": "mock-model"}},
20
+ "settings": {"default_markdown_output": True, "default_llm_profile": "default"},
21
+ "blueprints": {}
22
+ }
23
+ mocker.patch('django.apps.apps.get_app_config', return_value=mock_instance)
24
+ return mock_instance
25
+
26
+ @pytest.mark.asyncio
27
+ async def test_echocraft_blueprint_run(mock_app_config): # Use the fixture
28
+ """Tests the basic run functionality of EchoCraftBlueprint."""
29
+ blueprint = EchoCraftBlueprint(blueprint_id="test_echo_run")
30
+ messages = [{"role": "user", "content": "Hello"}]
31
+ expected_output = "Echo: Hello"
32
+
33
+ results = await collect_results(blueprint.run(messages))
34
+
35
+ assert len(results) > 0
36
+ final_message = results[-1]
37
+ assert "id" in final_message
38
+ assert "object" in final_message
39
+ assert final_message["object"] == "chat.completion"
40
+ assert "choices" in final_message
41
+ assert len(final_message["choices"]) == 1
42
+ assert "message" in final_message["choices"][0]
43
+ assert final_message["choices"][0]["message"]["role"] == "assistant"
44
+ assert final_message["choices"][0]["message"]["content"] == expected_output
45
+
46
+ @pytest.mark.asyncio
47
+ async def test_echocraft_blueprint_no_user_message(mock_app_config): # Use the fixture
48
+ """Tests that EchoCraft handles cases with no user message gracefully."""
49
+ blueprint = EchoCraftBlueprint(blueprint_id="test_echo_nouser")
50
+ messages = [{"role": "system", "content": "You are an echo bot."}]
51
+ # --- CORRECTED expected_output ---
52
+ expected_output = "Echo: No user message found."
53
+
54
+ results = await collect_results(blueprint.run(messages))
55
+
56
+ assert len(results) > 0
57
+ final_message = results[-1]
58
+ assert final_message["choices"][0]["message"]["content"] == expected_output
59
+
60
+ @pytest.mark.asyncio
61
+ async def test_echocraft_blueprint_multiple_messages(mock_app_config): # Use the fixture
62
+ """Tests that EchoCraft uses the *last* user message."""
63
+ blueprint = EchoCraftBlueprint(blueprint_id="test_echo_multi")
64
+ messages = [
65
+ {"role": "user", "content": "First"},
66
+ {"role": "assistant", "content": "Ignore me"},
67
+ {"role": "user", "content": "Second"},
68
+ ]
69
+ expected_output = "Echo: Second"
70
+
71
+ results = await collect_results(blueprint.run(messages))
72
+
73
+ assert len(results) > 0
74
+ final_message = results[-1]
75
+ assert final_message["choices"][0]["message"]["content"] == expected_output
76
+
@@ -0,0 +1,206 @@
1
+
2
+ # --- Content for tests/cli/test_launchers.py ---
3
+ import pytest
4
+ import subprocess
5
+ import sys
6
+ import os
7
+ import pathlib
8
+ from typer.testing import CliRunner
9
+ from unittest.mock import patch, MagicMock
10
+
11
+ # Corrected import path
12
+ from swarm.extensions.launchers import swarm_cli
13
+
14
+ runner = CliRunner()
15
+
16
+ EXPECTED_EXE_NAME = "test_blueprint"
17
+
18
+ @pytest.fixture
19
+ def mock_dirs(tmp_path):
20
+ """Creates temporary directories and returns their paths."""
21
+ mock_user_data_dir = tmp_path / "user_data"
22
+ mock_user_bin_dir = mock_user_data_dir / "bin"
23
+ mock_user_blueprints_dir = mock_user_data_dir / "blueprints"
24
+
25
+ mock_user_bin_dir.mkdir(parents=True, exist_ok=True)
26
+ mock_user_blueprints_dir.mkdir(parents=True, exist_ok=True)
27
+
28
+ return {
29
+ "data": mock_user_data_dir,
30
+ "bin": mock_user_bin_dir,
31
+ "blueprints": mock_user_blueprints_dir,
32
+ }
33
+
34
+ # This fixture is needed because mock_dirs uses mocker
35
+ @pytest.fixture(autouse=True)
36
+ def apply_mocker(mocker):
37
+ pass
38
+
39
+ @pytest.fixture
40
+ def mock_subprocess_run():
41
+ """Mocks subprocess.run."""
42
+ with patch("subprocess.run") as mock_run:
43
+ mock_process = MagicMock()
44
+ mock_process.returncode = 0
45
+ mock_process.stdout = "Success"
46
+ mock_process.stderr = ""
47
+ mock_run.return_value = mock_process
48
+ yield mock_run
49
+
50
+
51
+ def test_swarm_cli_entrypoint():
52
+ """Test that the CLI runs and shows help."""
53
+ result = runner.invoke(swarm_cli.app, ["--help"])
54
+ assert result.exit_code == 0
55
+ assert "[OPTIONS] COMMAND [ARGS]..." in result.stdout
56
+ assert "Swarm CLI tool" in result.stdout
57
+
58
+
59
+ @patch("subprocess.run")
60
+ def test_swarm_cli_install_creates_executable(mock_run, mock_dirs, mocker):
61
+ """Test the install command attempts to run PyInstaller."""
62
+ install_bin_dir = mock_dirs["bin"]
63
+ blueprints_src_dir = mock_dirs["blueprints"]
64
+ user_data_dir = mock_dirs["data"]
65
+
66
+ blueprint_name = "test_blueprint"
67
+ target_path = install_bin_dir / blueprint_name
68
+
69
+ # Simulate Source Blueprint Directory and File
70
+ source_dir = blueprints_src_dir / blueprint_name
71
+ source_dir.mkdir()
72
+ entry_point_name = "main.py"
73
+ entry_point_path = source_dir / entry_point_name
74
+ entry_point_path.write_text("print('hello from blueprint')")
75
+
76
+ # Mock find_entry_point
77
+ mocker.patch("swarm.extensions.launchers.swarm_cli.find_entry_point", return_value=entry_point_name)
78
+
79
+ # Configure mock for successful PyInstaller run
80
+ mock_process = MagicMock()
81
+ mock_process.returncode = 0
82
+ mock_process.stdout = f"PyInstaller finished successfully. Executable at {target_path}"
83
+ mock_process.stderr = ""
84
+ mock_run.return_value = mock_process
85
+
86
+ # --- Patch Module-Level Variables Directly ---
87
+ mocker.patch.object(swarm_cli, 'BLUEPRINTS_DIR', blueprints_src_dir)
88
+ mocker.patch.object(swarm_cli, 'INSTALLED_BIN_DIR', install_bin_dir)
89
+ mocker.patch.object(swarm_cli, 'USER_DATA_DIR', user_data_dir)
90
+
91
+ result = runner.invoke(swarm_cli.app, ["install", blueprint_name])
92
+
93
+ print(f"CLI Output:\n{result.output}")
94
+ print(f"CLI Exit Code: {result.exit_code}")
95
+ print(f"CLI Exception: {result.exception}")
96
+
97
+ assert result.exit_code == 0, f"CLI failed unexpectedly. Output:\n{result.output}"
98
+ assert f"Installing blueprint '{blueprint_name}'..." in result.output
99
+ assert f"Successfully installed '{blueprint_name}' to {target_path}" in result.output
100
+
101
+ mock_run.assert_called_once()
102
+ args, kwargs = mock_run.call_args
103
+ cmd_list = args[0] # Get the command list
104
+ assert "pyinstaller" in cmd_list[0]
105
+ assert str(entry_point_path) in cmd_list
106
+ # --- Corrected --name assertion ---
107
+ assert "--name" in cmd_list
108
+ assert cmd_list[cmd_list.index("--name") + 1] == blueprint_name
109
+ # --- End correction ---
110
+ assert "--distpath" in cmd_list
111
+ assert cmd_list[cmd_list.index("--distpath") + 1] == str(install_bin_dir)
112
+ assert "--workpath" in cmd_list
113
+ assert cmd_list[cmd_list.index("--workpath") + 1] == str(user_data_dir / "build") # Check specific build path
114
+ assert "--specpath" in cmd_list
115
+ assert cmd_list[cmd_list.index("--specpath") + 1] == str(user_data_dir)
116
+
117
+
118
+ @patch("subprocess.run")
119
+ def test_swarm_install_failure(mock_run, mock_dirs, mocker):
120
+ """Test the install command handles PyInstaller failure."""
121
+ install_bin_dir = mock_dirs["bin"]
122
+ blueprints_src_dir = mock_dirs["blueprints"]
123
+ user_data_dir = mock_dirs["data"]
124
+ blueprint_name = "fail_blueprint"
125
+
126
+ # Simulate Source Blueprint Directory and File
127
+ source_dir = blueprints_src_dir / blueprint_name
128
+ source_dir.mkdir()
129
+ entry_point_name = "fail_main.py"
130
+ entry_point_path = source_dir / entry_point_name
131
+ entry_point_path.write_text("print('fail')")
132
+
133
+ # Mock find_entry_point
134
+ mocker.patch("swarm.extensions.launchers.swarm_cli.find_entry_point", return_value=entry_point_name)
135
+
136
+ # --- Configure mock to RAISE CalledProcessError ---
137
+ error_stderr = "PyInstaller error: Build failed!"
138
+ mock_run.side_effect = subprocess.CalledProcessError(
139
+ returncode=1, cmd=["pyinstaller", "..."], stderr=error_stderr
140
+ )
141
+ # --- End change ---
142
+
143
+ # --- Patch Module-Level Variables Directly ---
144
+ mocker.patch.object(swarm_cli, 'BLUEPRINTS_DIR', blueprints_src_dir)
145
+ mocker.patch.object(swarm_cli, 'INSTALLED_BIN_DIR', install_bin_dir)
146
+ mocker.patch.object(swarm_cli, 'USER_DATA_DIR', user_data_dir)
147
+
148
+ result = runner.invoke(swarm_cli.app, ["install", blueprint_name])
149
+
150
+ assert result.exit_code == 1
151
+ assert f"Error during PyInstaller execution" in result.output
152
+ assert error_stderr in result.output
153
+
154
+
155
+ @patch("subprocess.run")
156
+ def test_swarm_launch_runs_executable(mock_run, mock_dirs, mocker):
157
+ """Test the launch command runs the correct executable."""
158
+ install_bin_dir = mock_dirs["bin"]
159
+ blueprint_name = EXPECTED_EXE_NAME
160
+ exe_path = install_bin_dir / blueprint_name
161
+
162
+ # Simulate the executable existing in the mocked bin dir
163
+ exe_path.touch(exist_ok=True)
164
+ exe_path.chmod(0o755)
165
+
166
+ mock_process = MagicMock()
167
+ mock_process.returncode = 0
168
+ mock_process.stdout = "Blueprint output"
169
+ mock_process.stderr = ""
170
+ mock_run.return_value = mock_process
171
+
172
+ # --- Patch Module-Level INSTALLED_BIN_DIR ---
173
+ mocker.patch.object(swarm_cli, 'INSTALLED_BIN_DIR', install_bin_dir)
174
+ # Patch file checks used by launch command
175
+ mocker.patch('pathlib.Path.is_file', return_value=True)
176
+ mocker.patch('os.access', return_value=True)
177
+
178
+ result = runner.invoke(
179
+ swarm_cli.app,
180
+ ["launch", blueprint_name], # No extra args
181
+ catch_exceptions=False,
182
+ )
183
+
184
+ assert result.exit_code == 0, f"CLI failed unexpectedly. Output:\n{result.output}"
185
+ assert f"Launching '{blueprint_name}' from {exe_path}..." in result.output
186
+ mock_run.assert_called_once_with([str(exe_path)], capture_output=True, text=True, check=False)
187
+
188
+
189
+ def test_swarm_launch_failure_not_found(mock_dirs, mocker):
190
+ """Test the launch command fails if the executable doesn't exist."""
191
+ install_bin_dir = mock_dirs["bin"]
192
+ blueprint_name = "nonexistent_blueprint"
193
+ expected_path = install_bin_dir / blueprint_name
194
+
195
+ # --- Patch Module-Level INSTALLED_BIN_DIR ---
196
+ mocker.patch.object(swarm_cli, 'INSTALLED_BIN_DIR', install_bin_dir)
197
+ # Patch file checks to return False
198
+ mocker.patch('pathlib.Path.is_file', return_value=False)
199
+ mocker.patch('os.access', return_value=False)
200
+
201
+ result = runner.invoke(swarm_cli.app, ["launch", blueprint_name])
202
+
203
+ assert result.exit_code == 1
204
+ expected_error = f"Error: Blueprint executable not found or not executable: {expected_path}"
205
+ assert expected_error in result.output.strip()
206
+
@@ -0,0 +1,106 @@
1
+
2
+ # --- Content for tests/unit/test_blueprint_base_config.py ---
3
+ import pytest
4
+ from pathlib import Path
5
+ from unittest.mock import patch, MagicMock, ANY
6
+ import os
7
+ from django.apps import apps # Import apps registry
8
+
9
+ # Assuming BlueprintBase is correctly importable now
10
+ from swarm.extensions.blueprint.blueprint_base import BlueprintBase
11
+ # No longer need to import SwarmConfig directly here
12
+
13
+ # A minimal concrete implementation for testing
14
+ class _TestableBlueprint(BlueprintBase):
15
+ async def run(self, messages, **kwargs):
16
+ yield {"result": "ok"}
17
+
18
+ # Fixture to mock the result of apps.get_app_config('swarm')
19
+ @pytest.fixture
20
+ def mock_app_config_instance(mocker):
21
+ # Create a mock instance that mimics the AppConfig instance
22
+ mock_instance = MagicMock()
23
+ # Set the 'config' attribute on the mock instance
24
+ mock_instance.config = {
25
+ "llm": {
26
+ "default": {"provider": "mock", "model": "mock-model"}
27
+ },
28
+ "settings": {
29
+ "default_markdown_output": True,
30
+ "default_llm_profile": "default"
31
+ },
32
+ "blueprints": {}
33
+ }
34
+ # Patch apps.get_app_config to return this mock instance
35
+ mocker.patch('django.apps.apps.get_app_config', return_value=mock_instance)
36
+ return mock_instance # Return the instance so tests can modify its .config
37
+
38
+
39
+ # Use the fixture in the test class
40
+ @pytest.mark.usefixtures("mock_app_config_instance")
41
+ class TestBlueprintBaseConfigLoading:
42
+
43
+ def test_init_does_not_raise(self):
44
+ """Test that basic initialization with mocked config works."""
45
+ try:
46
+ blueprint = _TestableBlueprint(blueprint_id="test_init")
47
+ assert blueprint.blueprint_id == "test_init"
48
+ assert blueprint.llm_profile_name == "default"
49
+ assert blueprint.llm_profile["provider"] == "mock"
50
+ assert blueprint.should_output_markdown is True
51
+ except Exception as e:
52
+ pytest.fail(f"BlueprintBase initialization failed: {e}")
53
+
54
+ @pytest.mark.skip(reason="Skipping due to Blueprint/Config refactor")
55
+ def test_get_llm_profile_success(self):
56
+ pass
57
+
58
+ @pytest.mark.skip(reason="Skipping due to Blueprint/Config refactor")
59
+ def test_get_llm_profile_missing_raises_error(self):
60
+ pass
61
+
62
+ def test_markdown_setting_priority(self, mock_app_config_instance): # Use the fixture
63
+ """Test markdown setting priority: blueprint > global."""
64
+
65
+ # --- Test Case 1: Global True, Blueprint unspecified -> True ---
66
+ mock_app_config_instance.config = { # Modify the config on the mock instance
67
+ "llm": {"default": {"provider": "mock"}},
68
+ "settings": {"default_markdown_output": True, "default_llm_profile": "default"},
69
+ "blueprints": {}
70
+ }
71
+ blueprint1 = _TestableBlueprint(blueprint_id="bp1")
72
+ assert blueprint1.should_output_markdown is True, "Should default to global True"
73
+
74
+ # --- Test Case 2: Global False, Blueprint unspecified -> False ---
75
+ mock_app_config_instance.config = {
76
+ "llm": {"default": {"provider": "mock"}},
77
+ "settings": {"default_markdown_output": False, "default_llm_profile": "default"},
78
+ "blueprints": {}
79
+ }
80
+ blueprint2 = _TestableBlueprint(blueprint_id="bp2")
81
+ assert blueprint2.should_output_markdown is False, "Should default to global False"
82
+
83
+ # --- Test Case 3: Global True, Blueprint False -> False ---
84
+ mock_app_config_instance.config = {
85
+ "llm": {"default": {"provider": "mock"}},
86
+ "settings": {"default_markdown_output": True, "default_llm_profile": "default"},
87
+ "blueprints": {"bp3": {"markdown_output": False}}
88
+ }
89
+ blueprint3 = _TestableBlueprint(blueprint_id="bp3")
90
+ assert blueprint3.should_output_markdown is False, "Blueprint setting (False) should override global (True)"
91
+
92
+ # --- Test Case 4: Global False, Blueprint True -> True ---
93
+ mock_app_config_instance.config = {
94
+ "llm": {"default": {"provider": "mock"}},
95
+ "settings": {"default_markdown_output": False, "default_llm_profile": "default"},
96
+ "blueprints": {"bp4": {"markdown_output": True}}
97
+ }
98
+ blueprint4 = _TestableBlueprint(blueprint_id="bp4")
99
+ assert blueprint4.should_output_markdown is True, "Blueprint setting (True) should override global (False)"
100
+
101
+
102
+ # Standalone tests (if any)
103
+ @pytest.mark.skip(reason="Skipping test: substitute_env_vars not found")
104
+ def test_substitute_env_vars_direct():
105
+ pass
106
+
@@ -1,44 +0,0 @@
1
- import logging
2
- from typing import Dict, List, Any, AsyncGenerator
3
- # Correct import path for BlueprintBase
4
- from swarm.extensions.blueprint.blueprint_base import BlueprintBase
5
-
6
- logger = logging.getLogger(__name__)
7
-
8
- class EchoCraftBlueprint(BlueprintBase):
9
- """
10
- A simple blueprint that echoes the last user message.
11
- """
12
- metadata = {
13
- "name": "EchoCraft",
14
- "description": "Echoes the last user message.",
15
- "author": "SwarmTeam",
16
- "version": "1.0",
17
- # Example: Specify a default LLM profile if desired
18
- # "llm_profile": "default"
19
- }
20
-
21
- # *** Make run async and use yield ***
22
- async def run(self, messages: List[Dict[str, str]]) -> AsyncGenerator[Dict[str, Any], None]:
23
- """
24
- Finds the last user message and yields it back with an 'Echo: ' prefix.
25
- """
26
- logger.info(f"EchoCraftBlueprint run called with {len(messages)} messages.")
27
- last_user_message = "No user message found."
28
- for msg in reversed(messages):
29
- if msg.get("role") == "user":
30
- last_user_message = msg.get("content", "")
31
- logger.debug(f"Found last user message: {last_user_message}")
32
- break
33
-
34
- response_content = f"Echo: {last_user_message}"
35
- logger.info(f"EchoCraftBlueprint yielding: {response_content}")
36
-
37
- # Yield the final response in the expected format
38
- yield {
39
- "messages": [
40
- {"role": "assistant", "content": response_content}
41
- ]
42
- }
43
- logger.info("EchoCraftBlueprint run finished.")
44
-