open-swarm 0.1.1743371228__tar.gz → 0.1.1743371918__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.
- {open_swarm-0.1.1743371228 → open_swarm-0.1.1743371918}/PKG-INFO +1 -1
- {open_swarm-0.1.1743371228 → open_swarm-0.1.1743371918}/pyproject.toml +1 -1
- open_swarm-0.1.1743371918/src/swarm/blueprints/echocraft/blueprint_echocraft.py +71 -0
- open_swarm-0.1.1743371918/src/swarm/extensions/blueprint/blueprint_base.py +111 -0
- open_swarm-0.1.1743371918/tests/blueprints/test_echocraft.py +76 -0
- open_swarm-0.1.1743371918/tests/cli/test_launchers.py +206 -0
- open_swarm-0.1.1743371918/tests/unit/test_blueprint_base_config.py +106 -0
- open_swarm-0.1.1743371228/src/swarm/blueprints/echocraft/blueprint_echocraft.py +0 -44
- open_swarm-0.1.1743371228/src/swarm/extensions/blueprint/blueprint_base.py +0 -160
- open_swarm-0.1.1743371228/tests/blueprints/test_echocraft.py +0 -75
- open_swarm-0.1.1743371228/tests/cli/test_launchers.py +0 -174
- open_swarm-0.1.1743371228/tests/unit/test_blueprint_base_config.py +0 -112
- {open_swarm-0.1.1743371228 → open_swarm-0.1.1743371918}/.gitignore +0 -0
- {open_swarm-0.1.1743371228 → open_swarm-0.1.1743371918}/LICENSE +0 -0
- {open_swarm-0.1.1743371228 → open_swarm-0.1.1743371918}/README.md +0 -0
- {open_swarm-0.1.1743371228 → open_swarm-0.1.1743371918}/src/swarm/__init__.py +0 -0
- {open_swarm-0.1.1743371228 → open_swarm-0.1.1743371918}/src/swarm/agent/__init__.py +0 -0
- {open_swarm-0.1.1743371228 → open_swarm-0.1.1743371918}/src/swarm/apps.py +0 -0
- {open_swarm-0.1.1743371228 → open_swarm-0.1.1743371918}/src/swarm/auth.py +0 -0
- {open_swarm-0.1.1743371228 → open_swarm-0.1.1743371918}/src/swarm/blueprints/README.md +0 -0
- {open_swarm-0.1.1743371228 → open_swarm-0.1.1743371918}/src/swarm/blueprints/burnt_noodles/blueprint_burnt_noodles.py +0 -0
- {open_swarm-0.1.1743371228 → open_swarm-0.1.1743371918}/src/swarm/blueprints/chatbot/blueprint_chatbot.py +0 -0
- {open_swarm-0.1.1743371228 → open_swarm-0.1.1743371918}/src/swarm/blueprints/chatbot/templates/chatbot/chatbot.html +0 -0
- {open_swarm-0.1.1743371228 → open_swarm-0.1.1743371918}/src/swarm/blueprints/digitalbutlers/blueprint_digitalbutlers.py +0 -0
- {open_swarm-0.1.1743371228 → open_swarm-0.1.1743371918}/src/swarm/blueprints/dilbot_universe/blueprint_dilbot_universe.py +0 -0
- {open_swarm-0.1.1743371228 → open_swarm-0.1.1743371918}/src/swarm/blueprints/divine_code/__init__.py +0 -0
- {open_swarm-0.1.1743371228 → open_swarm-0.1.1743371918}/src/swarm/blueprints/divine_code/apps.py +0 -0
- {open_swarm-0.1.1743371228 → open_swarm-0.1.1743371918}/src/swarm/blueprints/divine_code/blueprint_divine_code.py +0 -0
- {open_swarm-0.1.1743371228 → open_swarm-0.1.1743371918}/src/swarm/blueprints/django_chat/apps.py +0 -0
- {open_swarm-0.1.1743371228 → open_swarm-0.1.1743371918}/src/swarm/blueprints/django_chat/blueprint_django_chat.py +0 -0
- {open_swarm-0.1.1743371228 → open_swarm-0.1.1743371918}/src/swarm/blueprints/django_chat/templates/django_chat/django_chat_webpage.html +0 -0
- {open_swarm-0.1.1743371228 → open_swarm-0.1.1743371918}/src/swarm/blueprints/django_chat/urls.py +0 -0
- {open_swarm-0.1.1743371228 → open_swarm-0.1.1743371918}/src/swarm/blueprints/django_chat/views.py +0 -0
- {open_swarm-0.1.1743371228 → open_swarm-0.1.1743371918}/src/swarm/blueprints/family_ties/apps.py +0 -0
- {open_swarm-0.1.1743371228 → open_swarm-0.1.1743371918}/src/swarm/blueprints/family_ties/blueprint_family_ties.py +0 -0
- {open_swarm-0.1.1743371228 → open_swarm-0.1.1743371918}/src/swarm/blueprints/family_ties/models.py +0 -0
- {open_swarm-0.1.1743371228 → open_swarm-0.1.1743371918}/src/swarm/blueprints/family_ties/serializers.py +0 -0
- {open_swarm-0.1.1743371228 → open_swarm-0.1.1743371918}/src/swarm/blueprints/family_ties/settings.py +0 -0
- {open_swarm-0.1.1743371228 → open_swarm-0.1.1743371918}/src/swarm/blueprints/family_ties/urls.py +0 -0
- {open_swarm-0.1.1743371228 → open_swarm-0.1.1743371918}/src/swarm/blueprints/family_ties/views.py +0 -0
- {open_swarm-0.1.1743371228 → open_swarm-0.1.1743371918}/src/swarm/blueprints/flock/__init__.py +0 -0
- {open_swarm-0.1.1743371228 → open_swarm-0.1.1743371918}/src/swarm/blueprints/gaggle/blueprint_gaggle.py +0 -0
- {open_swarm-0.1.1743371228 → open_swarm-0.1.1743371918}/src/swarm/blueprints/gotchaman/blueprint_gotchaman.py +0 -0
- {open_swarm-0.1.1743371228 → open_swarm-0.1.1743371918}/src/swarm/blueprints/mcp_demo/blueprint_mcp_demo.py +0 -0
- {open_swarm-0.1.1743371228 → open_swarm-0.1.1743371918}/src/swarm/blueprints/messenger/templates/messenger/messenger.html +0 -0
- {open_swarm-0.1.1743371228 → open_swarm-0.1.1743371918}/src/swarm/blueprints/mission_improbable/blueprint_mission_improbable.py +0 -0
- {open_swarm-0.1.1743371228 → open_swarm-0.1.1743371918}/src/swarm/blueprints/monkai_magic/blueprint_monkai_magic.py +0 -0
- {open_swarm-0.1.1743371228 → open_swarm-0.1.1743371918}/src/swarm/blueprints/nebula_shellz/blueprint_nebula_shellz.py +0 -0
- {open_swarm-0.1.1743371228 → open_swarm-0.1.1743371918}/src/swarm/blueprints/omniplex/blueprint_omniplex.py +0 -0
- {open_swarm-0.1.1743371228 → open_swarm-0.1.1743371918}/src/swarm/blueprints/rue_code/__init__.py +0 -0
- {open_swarm-0.1.1743371228 → open_swarm-0.1.1743371918}/src/swarm/blueprints/rue_code/blueprint_rue_code.py +0 -0
- {open_swarm-0.1.1743371228 → open_swarm-0.1.1743371918}/src/swarm/blueprints/suggestion/blueprint_suggestion.py +0 -0
- {open_swarm-0.1.1743371228 → open_swarm-0.1.1743371918}/src/swarm/blueprints/unapologetic_press/blueprint_unapologetic_press.py +0 -0
- {open_swarm-0.1.1743371228 → open_swarm-0.1.1743371918}/src/swarm/blueprints/whiskeytango_foxtrot/__init__.py +0 -0
- {open_swarm-0.1.1743371228 → open_swarm-0.1.1743371918}/src/swarm/blueprints/whiskeytango_foxtrot/apps.py +0 -0
- {open_swarm-0.1.1743371228 → open_swarm-0.1.1743371918}/src/swarm/blueprints/whiskeytango_foxtrot/blueprint_whiskeytango_foxtrot.py +0 -0
- {open_swarm-0.1.1743371228 → open_swarm-0.1.1743371918}/src/swarm/consumers.py +0 -0
- {open_swarm-0.1.1743371228 → open_swarm-0.1.1743371918}/src/swarm/extensions/__init__.py +0 -0
- {open_swarm-0.1.1743371228 → open_swarm-0.1.1743371918}/src/swarm/extensions/blueprint/__init__.py +0 -0
- {open_swarm-0.1.1743371228 → open_swarm-0.1.1743371918}/src/swarm/extensions/blueprint/agent_utils.py +0 -0
- {open_swarm-0.1.1743371228 → open_swarm-0.1.1743371918}/src/swarm/extensions/blueprint/blueprint_discovery.py +0 -0
- {open_swarm-0.1.1743371228 → open_swarm-0.1.1743371918}/src/swarm/extensions/blueprint/blueprint_utils.py +0 -0
- {open_swarm-0.1.1743371228 → open_swarm-0.1.1743371918}/src/swarm/extensions/blueprint/cli_handler.py +0 -0
- {open_swarm-0.1.1743371228 → open_swarm-0.1.1743371918}/src/swarm/extensions/blueprint/common_utils.py +0 -0
- {open_swarm-0.1.1743371228 → open_swarm-0.1.1743371918}/src/swarm/extensions/blueprint/config_loader.py +0 -0
- {open_swarm-0.1.1743371228 → open_swarm-0.1.1743371918}/src/swarm/extensions/blueprint/django_utils.py +0 -0
- {open_swarm-0.1.1743371228 → open_swarm-0.1.1743371918}/src/swarm/extensions/blueprint/interactive_mode.py +0 -0
- {open_swarm-0.1.1743371228 → open_swarm-0.1.1743371918}/src/swarm/extensions/blueprint/modes/rest_mode.py +0 -0
- {open_swarm-0.1.1743371228 → open_swarm-0.1.1743371918}/src/swarm/extensions/blueprint/output_utils.py +0 -0
- {open_swarm-0.1.1743371228 → open_swarm-0.1.1743371918}/src/swarm/extensions/blueprint/spinner.py +0 -0
- {open_swarm-0.1.1743371228 → open_swarm-0.1.1743371918}/src/swarm/extensions/cli/__init__.py +0 -0
- {open_swarm-0.1.1743371228 → open_swarm-0.1.1743371918}/src/swarm/extensions/cli/blueprint_runner.py +0 -0
- {open_swarm-0.1.1743371228 → open_swarm-0.1.1743371918}/src/swarm/extensions/cli/cli_args.py +0 -0
- {open_swarm-0.1.1743371228 → open_swarm-0.1.1743371918}/src/swarm/extensions/cli/commands/__init__.py +0 -0
- {open_swarm-0.1.1743371228 → open_swarm-0.1.1743371918}/src/swarm/extensions/cli/commands/blueprint_management.py +0 -0
- {open_swarm-0.1.1743371228 → open_swarm-0.1.1743371918}/src/swarm/extensions/cli/commands/config_management.py +0 -0
- {open_swarm-0.1.1743371228 → open_swarm-0.1.1743371918}/src/swarm/extensions/cli/commands/edit_config.py +0 -0
- {open_swarm-0.1.1743371228 → open_swarm-0.1.1743371918}/src/swarm/extensions/cli/commands/list_blueprints.py +0 -0
- {open_swarm-0.1.1743371228 → open_swarm-0.1.1743371918}/src/swarm/extensions/cli/commands/validate_env.py +0 -0
- {open_swarm-0.1.1743371228 → open_swarm-0.1.1743371918}/src/swarm/extensions/cli/commands/validate_envvars.py +0 -0
- {open_swarm-0.1.1743371228 → open_swarm-0.1.1743371918}/src/swarm/extensions/cli/interactive_shell.py +0 -0
- {open_swarm-0.1.1743371228 → open_swarm-0.1.1743371918}/src/swarm/extensions/cli/main.py +0 -0
- {open_swarm-0.1.1743371228 → open_swarm-0.1.1743371918}/src/swarm/extensions/cli/selection.py +0 -0
- {open_swarm-0.1.1743371228 → open_swarm-0.1.1743371918}/src/swarm/extensions/cli/utils/discover_commands.py +0 -0
- {open_swarm-0.1.1743371228 → open_swarm-0.1.1743371918}/src/swarm/extensions/cli/utils/env_setup.py +0 -0
- {open_swarm-0.1.1743371228 → open_swarm-0.1.1743371918}/src/swarm/extensions/cli/utils.py +0 -0
- {open_swarm-0.1.1743371228 → open_swarm-0.1.1743371918}/src/swarm/extensions/config/__init__.py +0 -0
- {open_swarm-0.1.1743371228 → open_swarm-0.1.1743371918}/src/swarm/extensions/config/config_loader.py +0 -0
- {open_swarm-0.1.1743371228 → open_swarm-0.1.1743371918}/src/swarm/extensions/config/config_manager.py +0 -0
- {open_swarm-0.1.1743371228 → open_swarm-0.1.1743371918}/src/swarm/extensions/config/server_config.py +0 -0
- {open_swarm-0.1.1743371228 → open_swarm-0.1.1743371918}/src/swarm/extensions/config/setup_wizard.py +0 -0
- {open_swarm-0.1.1743371228 → open_swarm-0.1.1743371918}/src/swarm/extensions/config/utils/__init__.py +0 -0
- {open_swarm-0.1.1743371228 → open_swarm-0.1.1743371918}/src/swarm/extensions/config/utils/logger.py +0 -0
- {open_swarm-0.1.1743371228 → open_swarm-0.1.1743371918}/src/swarm/extensions/launchers/__init__.py +0 -0
- {open_swarm-0.1.1743371228 → open_swarm-0.1.1743371918}/src/swarm/extensions/launchers/build_launchers.py +0 -0
- {open_swarm-0.1.1743371228 → open_swarm-0.1.1743371918}/src/swarm/extensions/launchers/build_swarm_wrapper.py +0 -0
- {open_swarm-0.1.1743371228 → open_swarm-0.1.1743371918}/src/swarm/extensions/launchers/swarm_api.py +0 -0
- {open_swarm-0.1.1743371228 → open_swarm-0.1.1743371918}/src/swarm/extensions/launchers/swarm_cli.py +0 -0
- {open_swarm-0.1.1743371228 → open_swarm-0.1.1743371918}/src/swarm/extensions/launchers/swarm_wrapper.py +0 -0
- {open_swarm-0.1.1743371228 → open_swarm-0.1.1743371918}/src/swarm/llm/chat_completion.py +0 -0
- {open_swarm-0.1.1743371228 → open_swarm-0.1.1743371918}/src/swarm/management/__init__.py +0 -0
- {open_swarm-0.1.1743371228 → open_swarm-0.1.1743371918}/src/swarm/management/commands/__init__.py +0 -0
- {open_swarm-0.1.1743371228 → open_swarm-0.1.1743371918}/src/swarm/management/commands/runserver.py +0 -0
- {open_swarm-0.1.1743371228 → open_swarm-0.1.1743371918}/src/swarm/messages.py +0 -0
- {open_swarm-0.1.1743371228 → open_swarm-0.1.1743371918}/src/swarm/migrations/0010_initial_chat_models.py +0 -0
- {open_swarm-0.1.1743371228 → open_swarm-0.1.1743371918}/src/swarm/migrations/__init__.py +0 -0
- {open_swarm-0.1.1743371228 → open_swarm-0.1.1743371918}/src/swarm/models.py +0 -0
- {open_swarm-0.1.1743371228 → open_swarm-0.1.1743371918}/src/swarm/permissions.py +0 -0
- {open_swarm-0.1.1743371228 → open_swarm-0.1.1743371918}/src/swarm/repl/__init__.py +0 -0
- {open_swarm-0.1.1743371228 → open_swarm-0.1.1743371918}/src/swarm/repl/repl.py +0 -0
- {open_swarm-0.1.1743371228 → open_swarm-0.1.1743371918}/src/swarm/serializers.py +0 -0
- {open_swarm-0.1.1743371228 → open_swarm-0.1.1743371918}/src/swarm/settings.py +0 -0
- {open_swarm-0.1.1743371228 → open_swarm-0.1.1743371918}/src/swarm/static/contrib/fonts/fontawesome-webfont.ttf +0 -0
- {open_swarm-0.1.1743371228 → open_swarm-0.1.1743371918}/src/swarm/static/contrib/fonts/fontawesome-webfont.woff +0 -0
- {open_swarm-0.1.1743371228 → open_swarm-0.1.1743371918}/src/swarm/static/contrib/fonts/fontawesome-webfont.woff2 +0 -0
- {open_swarm-0.1.1743371228 → open_swarm-0.1.1743371918}/src/swarm/static/contrib/markedjs/marked.min.js +0 -0
- {open_swarm-0.1.1743371228 → open_swarm-0.1.1743371918}/src/swarm/static/contrib/tabler-icons/adjustments-horizontal.svg +0 -0
- {open_swarm-0.1.1743371228 → open_swarm-0.1.1743371918}/src/swarm/static/contrib/tabler-icons/alert-triangle.svg +0 -0
- {open_swarm-0.1.1743371228 → open_swarm-0.1.1743371918}/src/swarm/static/contrib/tabler-icons/archive.svg +0 -0
- {open_swarm-0.1.1743371228 → open_swarm-0.1.1743371918}/src/swarm/static/contrib/tabler-icons/artboard.svg +0 -0
- {open_swarm-0.1.1743371228 → open_swarm-0.1.1743371918}/src/swarm/static/contrib/tabler-icons/automatic-gearbox.svg +0 -0
- {open_swarm-0.1.1743371228 → open_swarm-0.1.1743371918}/src/swarm/static/contrib/tabler-icons/box-multiple.svg +0 -0
- {open_swarm-0.1.1743371228 → open_swarm-0.1.1743371918}/src/swarm/static/contrib/tabler-icons/carambola.svg +0 -0
- {open_swarm-0.1.1743371228 → open_swarm-0.1.1743371918}/src/swarm/static/contrib/tabler-icons/copy.svg +0 -0
- {open_swarm-0.1.1743371228 → open_swarm-0.1.1743371918}/src/swarm/static/contrib/tabler-icons/download.svg +0 -0
- {open_swarm-0.1.1743371228 → open_swarm-0.1.1743371918}/src/swarm/static/contrib/tabler-icons/edit.svg +0 -0
- {open_swarm-0.1.1743371228 → open_swarm-0.1.1743371918}/src/swarm/static/contrib/tabler-icons/filled/carambola.svg +0 -0
- {open_swarm-0.1.1743371228 → open_swarm-0.1.1743371918}/src/swarm/static/contrib/tabler-icons/filled/paint.svg +0 -0
- {open_swarm-0.1.1743371228 → open_swarm-0.1.1743371918}/src/swarm/static/contrib/tabler-icons/headset.svg +0 -0
- {open_swarm-0.1.1743371228 → open_swarm-0.1.1743371918}/src/swarm/static/contrib/tabler-icons/layout-sidebar-left-collapse.svg +0 -0
- {open_swarm-0.1.1743371228 → open_swarm-0.1.1743371918}/src/swarm/static/contrib/tabler-icons/layout-sidebar-left-expand.svg +0 -0
- {open_swarm-0.1.1743371228 → open_swarm-0.1.1743371918}/src/swarm/static/contrib/tabler-icons/layout-sidebar-right-collapse.svg +0 -0
- {open_swarm-0.1.1743371228 → open_swarm-0.1.1743371918}/src/swarm/static/contrib/tabler-icons/layout-sidebar-right-expand.svg +0 -0
- {open_swarm-0.1.1743371228 → open_swarm-0.1.1743371918}/src/swarm/static/contrib/tabler-icons/message-chatbot.svg +0 -0
- {open_swarm-0.1.1743371228 → open_swarm-0.1.1743371918}/src/swarm/static/contrib/tabler-icons/message-star.svg +0 -0
- {open_swarm-0.1.1743371228 → open_swarm-0.1.1743371918}/src/swarm/static/contrib/tabler-icons/message-x.svg +0 -0
- {open_swarm-0.1.1743371228 → open_swarm-0.1.1743371918}/src/swarm/static/contrib/tabler-icons/message.svg +0 -0
- {open_swarm-0.1.1743371228 → open_swarm-0.1.1743371918}/src/swarm/static/contrib/tabler-icons/paperclip.svg +0 -0
- {open_swarm-0.1.1743371228 → open_swarm-0.1.1743371918}/src/swarm/static/contrib/tabler-icons/playlist-add.svg +0 -0
- {open_swarm-0.1.1743371228 → open_swarm-0.1.1743371918}/src/swarm/static/contrib/tabler-icons/robot.svg +0 -0
- {open_swarm-0.1.1743371228 → open_swarm-0.1.1743371918}/src/swarm/static/contrib/tabler-icons/search.svg +0 -0
- {open_swarm-0.1.1743371228 → open_swarm-0.1.1743371918}/src/swarm/static/contrib/tabler-icons/settings.svg +0 -0
- {open_swarm-0.1.1743371228 → open_swarm-0.1.1743371918}/src/swarm/static/contrib/tabler-icons/thumb-down.svg +0 -0
- {open_swarm-0.1.1743371228 → open_swarm-0.1.1743371918}/src/swarm/static/contrib/tabler-icons/thumb-up.svg +0 -0
- {open_swarm-0.1.1743371228 → open_swarm-0.1.1743371918}/src/swarm/static/css/dropdown.css +0 -0
- {open_swarm-0.1.1743371228 → open_swarm-0.1.1743371918}/src/swarm/static/htmx/htmx.min.js +0 -0
- {open_swarm-0.1.1743371228 → open_swarm-0.1.1743371918}/src/swarm/static/js/dropdown.js +0 -0
- {open_swarm-0.1.1743371228 → open_swarm-0.1.1743371918}/src/swarm/static/rest_mode/css/base.css +0 -0
- {open_swarm-0.1.1743371228 → open_swarm-0.1.1743371918}/src/swarm/static/rest_mode/css/chat-history.css +0 -0
- {open_swarm-0.1.1743371228 → open_swarm-0.1.1743371918}/src/swarm/static/rest_mode/css/chat.css +0 -0
- {open_swarm-0.1.1743371228 → open_swarm-0.1.1743371918}/src/swarm/static/rest_mode/css/chatbot.css +0 -0
- {open_swarm-0.1.1743371228 → open_swarm-0.1.1743371918}/src/swarm/static/rest_mode/css/chatgpt.css +0 -0
- {open_swarm-0.1.1743371228 → open_swarm-0.1.1743371918}/src/swarm/static/rest_mode/css/colors/corporate.css +0 -0
- {open_swarm-0.1.1743371228 → open_swarm-0.1.1743371918}/src/swarm/static/rest_mode/css/colors/pastel.css +0 -0
- {open_swarm-0.1.1743371228 → open_swarm-0.1.1743371918}/src/swarm/static/rest_mode/css/colors/tropical.css +0 -0
- {open_swarm-0.1.1743371228 → open_swarm-0.1.1743371918}/src/swarm/static/rest_mode/css/general.css +0 -0
- {open_swarm-0.1.1743371228 → open_swarm-0.1.1743371918}/src/swarm/static/rest_mode/css/layout.css +0 -0
- {open_swarm-0.1.1743371228 → open_swarm-0.1.1743371918}/src/swarm/static/rest_mode/css/layouts/messenger-layout.css +0 -0
- {open_swarm-0.1.1743371228 → open_swarm-0.1.1743371918}/src/swarm/static/rest_mode/css/layouts/minimalist-layout.css +0 -0
- {open_swarm-0.1.1743371228 → open_swarm-0.1.1743371918}/src/swarm/static/rest_mode/css/layouts/mobile-layout.css +0 -0
- {open_swarm-0.1.1743371228 → open_swarm-0.1.1743371918}/src/swarm/static/rest_mode/css/messages.css +0 -0
- {open_swarm-0.1.1743371228 → open_swarm-0.1.1743371918}/src/swarm/static/rest_mode/css/messenger.css +0 -0
- {open_swarm-0.1.1743371228 → open_swarm-0.1.1743371918}/src/swarm/static/rest_mode/css/settings.css +0 -0
- {open_swarm-0.1.1743371228 → open_swarm-0.1.1743371918}/src/swarm/static/rest_mode/css/simple.css +0 -0
- {open_swarm-0.1.1743371228 → open_swarm-0.1.1743371918}/src/swarm/static/rest_mode/css/slack.css +0 -0
- {open_swarm-0.1.1743371228 → open_swarm-0.1.1743371918}/src/swarm/static/rest_mode/css/style.css +0 -0
- {open_swarm-0.1.1743371228 → open_swarm-0.1.1743371918}/src/swarm/static/rest_mode/css/theme.css +0 -0
- {open_swarm-0.1.1743371228 → open_swarm-0.1.1743371918}/src/swarm/static/rest_mode/css/toast.css +0 -0
- {open_swarm-0.1.1743371228 → open_swarm-0.1.1743371918}/src/swarm/static/rest_mode/js/auth.js +0 -0
- {open_swarm-0.1.1743371228 → open_swarm-0.1.1743371918}/src/swarm/static/rest_mode/js/blueprint.js +0 -0
- {open_swarm-0.1.1743371228 → open_swarm-0.1.1743371918}/src/swarm/static/rest_mode/js/blueprintUtils.js +0 -0
- {open_swarm-0.1.1743371228 → open_swarm-0.1.1743371918}/src/swarm/static/rest_mode/js/chatLogic.js +0 -0
- {open_swarm-0.1.1743371228 → open_swarm-0.1.1743371918}/src/swarm/static/rest_mode/js/debug.js +0 -0
- {open_swarm-0.1.1743371228 → open_swarm-0.1.1743371918}/src/swarm/static/rest_mode/js/events.js +0 -0
- {open_swarm-0.1.1743371228 → open_swarm-0.1.1743371918}/src/swarm/static/rest_mode/js/main.js +0 -0
- {open_swarm-0.1.1743371228 → open_swarm-0.1.1743371918}/src/swarm/static/rest_mode/js/messages.js +0 -0
- {open_swarm-0.1.1743371228 → open_swarm-0.1.1743371918}/src/swarm/static/rest_mode/js/messengerLogic.js +0 -0
- {open_swarm-0.1.1743371228 → open_swarm-0.1.1743371918}/src/swarm/static/rest_mode/js/modules/apiService.js +0 -0
- {open_swarm-0.1.1743371228 → open_swarm-0.1.1743371918}/src/swarm/static/rest_mode/js/modules/blueprintManager.js +0 -0
- {open_swarm-0.1.1743371228 → open_swarm-0.1.1743371918}/src/swarm/static/rest_mode/js/modules/chatHistory.js +0 -0
- {open_swarm-0.1.1743371228 → open_swarm-0.1.1743371918}/src/swarm/static/rest_mode/js/modules/debugLogger.js +0 -0
- {open_swarm-0.1.1743371228 → open_swarm-0.1.1743371918}/src/swarm/static/rest_mode/js/modules/eventHandlers.js +0 -0
- {open_swarm-0.1.1743371228 → open_swarm-0.1.1743371918}/src/swarm/static/rest_mode/js/modules/messageProcessor.js +0 -0
- {open_swarm-0.1.1743371228 → open_swarm-0.1.1743371918}/src/swarm/static/rest_mode/js/modules/state.js +0 -0
- {open_swarm-0.1.1743371228 → open_swarm-0.1.1743371918}/src/swarm/static/rest_mode/js/modules/userInteractions.js +0 -0
- {open_swarm-0.1.1743371228 → open_swarm-0.1.1743371918}/src/swarm/static/rest_mode/js/modules/validation.js +0 -0
- {open_swarm-0.1.1743371228 → open_swarm-0.1.1743371918}/src/swarm/static/rest_mode/js/rendering.js +0 -0
- {open_swarm-0.1.1743371228 → open_swarm-0.1.1743371918}/src/swarm/static/rest_mode/js/settings.js +0 -0
- {open_swarm-0.1.1743371228 → open_swarm-0.1.1743371918}/src/swarm/static/rest_mode/js/sidebar.js +0 -0
- {open_swarm-0.1.1743371228 → open_swarm-0.1.1743371918}/src/swarm/static/rest_mode/js/simpleLogic.js +0 -0
- {open_swarm-0.1.1743371228 → open_swarm-0.1.1743371918}/src/swarm/static/rest_mode/js/slackLogic.js +0 -0
- {open_swarm-0.1.1743371228 → open_swarm-0.1.1743371918}/src/swarm/static/rest_mode/js/splash.js +0 -0
- {open_swarm-0.1.1743371228 → open_swarm-0.1.1743371918}/src/swarm/static/rest_mode/js/theme.js +0 -0
- {open_swarm-0.1.1743371228 → open_swarm-0.1.1743371918}/src/swarm/static/rest_mode/js/toast.js +0 -0
- {open_swarm-0.1.1743371228 → open_swarm-0.1.1743371918}/src/swarm/static/rest_mode/js/ui.js +0 -0
- {open_swarm-0.1.1743371228 → open_swarm-0.1.1743371918}/src/swarm/static/rest_mode/js/validation.js +0 -0
- {open_swarm-0.1.1743371228 → open_swarm-0.1.1743371918}/src/swarm/static/rest_mode/svg/animated_spinner.svg +0 -0
- {open_swarm-0.1.1743371228 → open_swarm-0.1.1743371918}/src/swarm/static/rest_mode/svg/arrow_down.svg +0 -0
- {open_swarm-0.1.1743371228 → open_swarm-0.1.1743371918}/src/swarm/static/rest_mode/svg/arrow_left.svg +0 -0
- {open_swarm-0.1.1743371228 → open_swarm-0.1.1743371918}/src/swarm/static/rest_mode/svg/arrow_right.svg +0 -0
- {open_swarm-0.1.1743371228 → open_swarm-0.1.1743371918}/src/swarm/static/rest_mode/svg/arrow_up.svg +0 -0
- {open_swarm-0.1.1743371228 → open_swarm-0.1.1743371918}/src/swarm/static/rest_mode/svg/attach.svg +0 -0
- {open_swarm-0.1.1743371228 → open_swarm-0.1.1743371918}/src/swarm/static/rest_mode/svg/avatar.svg +0 -0
- {open_swarm-0.1.1743371228 → open_swarm-0.1.1743371918}/src/swarm/static/rest_mode/svg/canvas.svg +0 -0
- {open_swarm-0.1.1743371228 → open_swarm-0.1.1743371918}/src/swarm/static/rest_mode/svg/chat_history.svg +0 -0
- {open_swarm-0.1.1743371228 → open_swarm-0.1.1743371918}/src/swarm/static/rest_mode/svg/close.svg +0 -0
- {open_swarm-0.1.1743371228 → open_swarm-0.1.1743371918}/src/swarm/static/rest_mode/svg/copy.svg +0 -0
- {open_swarm-0.1.1743371228 → open_swarm-0.1.1743371918}/src/swarm/static/rest_mode/svg/dark_mode.svg +0 -0
- {open_swarm-0.1.1743371228 → open_swarm-0.1.1743371918}/src/swarm/static/rest_mode/svg/edit.svg +0 -0
- {open_swarm-0.1.1743371228 → open_swarm-0.1.1743371918}/src/swarm/static/rest_mode/svg/layout.svg +0 -0
- {open_swarm-0.1.1743371228 → open_swarm-0.1.1743371918}/src/swarm/static/rest_mode/svg/logo.svg +0 -0
- {open_swarm-0.1.1743371228 → open_swarm-0.1.1743371918}/src/swarm/static/rest_mode/svg/logout.svg +0 -0
- {open_swarm-0.1.1743371228 → open_swarm-0.1.1743371918}/src/swarm/static/rest_mode/svg/mobile.svg +0 -0
- {open_swarm-0.1.1743371228 → open_swarm-0.1.1743371918}/src/swarm/static/rest_mode/svg/new_chat.svg +0 -0
- {open_swarm-0.1.1743371228 → open_swarm-0.1.1743371918}/src/swarm/static/rest_mode/svg/not_visible.svg +0 -0
- {open_swarm-0.1.1743371228 → open_swarm-0.1.1743371918}/src/swarm/static/rest_mode/svg/plus.svg +0 -0
- {open_swarm-0.1.1743371228 → open_swarm-0.1.1743371918}/src/swarm/static/rest_mode/svg/run_code.svg +0 -0
- {open_swarm-0.1.1743371228 → open_swarm-0.1.1743371918}/src/swarm/static/rest_mode/svg/save.svg +0 -0
- {open_swarm-0.1.1743371228 → open_swarm-0.1.1743371918}/src/swarm/static/rest_mode/svg/search.svg +0 -0
- {open_swarm-0.1.1743371228 → open_swarm-0.1.1743371918}/src/swarm/static/rest_mode/svg/settings.svg +0 -0
- {open_swarm-0.1.1743371228 → open_swarm-0.1.1743371918}/src/swarm/static/rest_mode/svg/speaker.svg +0 -0
- {open_swarm-0.1.1743371228 → open_swarm-0.1.1743371918}/src/swarm/static/rest_mode/svg/stop.svg +0 -0
- {open_swarm-0.1.1743371228 → open_swarm-0.1.1743371918}/src/swarm/static/rest_mode/svg/thumbs_down.svg +0 -0
- {open_swarm-0.1.1743371228 → open_swarm-0.1.1743371918}/src/swarm/static/rest_mode/svg/thumbs_up.svg +0 -0
- {open_swarm-0.1.1743371228 → open_swarm-0.1.1743371918}/src/swarm/static/rest_mode/svg/toggle_off.svg +0 -0
- {open_swarm-0.1.1743371228 → open_swarm-0.1.1743371918}/src/swarm/static/rest_mode/svg/toggle_on.svg +0 -0
- {open_swarm-0.1.1743371228 → open_swarm-0.1.1743371918}/src/swarm/static/rest_mode/svg/trash.svg +0 -0
- {open_swarm-0.1.1743371228 → open_swarm-0.1.1743371918}/src/swarm/static/rest_mode/svg/undo.svg +0 -0
- {open_swarm-0.1.1743371228 → open_swarm-0.1.1743371918}/src/swarm/static/rest_mode/svg/visible.svg +0 -0
- {open_swarm-0.1.1743371228 → open_swarm-0.1.1743371918}/src/swarm/static/rest_mode/svg/voice.svg +0 -0
- {open_swarm-0.1.1743371228 → open_swarm-0.1.1743371918}/src/swarm/templates/account/login.html +0 -0
- {open_swarm-0.1.1743371228 → open_swarm-0.1.1743371918}/src/swarm/templates/account/signup.html +0 -0
- {open_swarm-0.1.1743371228 → open_swarm-0.1.1743371918}/src/swarm/templates/base.html +0 -0
- {open_swarm-0.1.1743371228 → open_swarm-0.1.1743371918}/src/swarm/templates/chat.html +0 -0
- {open_swarm-0.1.1743371228 → open_swarm-0.1.1743371918}/src/swarm/templates/index.html +0 -0
- {open_swarm-0.1.1743371228 → open_swarm-0.1.1743371918}/src/swarm/templates/rest_mode/components/chat_sidebar.html +0 -0
- {open_swarm-0.1.1743371228 → open_swarm-0.1.1743371918}/src/swarm/templates/rest_mode/components/header.html +0 -0
- {open_swarm-0.1.1743371228 → open_swarm-0.1.1743371918}/src/swarm/templates/rest_mode/components/main_chat_pane.html +0 -0
- {open_swarm-0.1.1743371228 → open_swarm-0.1.1743371918}/src/swarm/templates/rest_mode/components/settings_dialog.html +0 -0
- {open_swarm-0.1.1743371228 → open_swarm-0.1.1743371918}/src/swarm/templates/rest_mode/components/splash_screen.html +0 -0
- {open_swarm-0.1.1743371228 → open_swarm-0.1.1743371918}/src/swarm/templates/rest_mode/components/top_bar.html +0 -0
- {open_swarm-0.1.1743371228 → open_swarm-0.1.1743371918}/src/swarm/templates/rest_mode/message_ui.html +0 -0
- {open_swarm-0.1.1743371228 → open_swarm-0.1.1743371918}/src/swarm/templates/rest_mode/slackbot.html +0 -0
- {open_swarm-0.1.1743371228 → open_swarm-0.1.1743371918}/src/swarm/templates/simple_blueprint_page.html +0 -0
- {open_swarm-0.1.1743371228 → open_swarm-0.1.1743371918}/src/swarm/templates/websocket_partials/final_system_message.html +0 -0
- {open_swarm-0.1.1743371228 → open_swarm-0.1.1743371918}/src/swarm/templates/websocket_partials/system_message.html +0 -0
- {open_swarm-0.1.1743371228 → open_swarm-0.1.1743371918}/src/swarm/templates/websocket_partials/user_message.html +0 -0
- {open_swarm-0.1.1743371228 → open_swarm-0.1.1743371918}/src/swarm/tool_executor.py +0 -0
- {open_swarm-0.1.1743371228 → open_swarm-0.1.1743371918}/src/swarm/urls.py +0 -0
- {open_swarm-0.1.1743371228 → open_swarm-0.1.1743371918}/src/swarm/util.py +0 -0
- {open_swarm-0.1.1743371228 → open_swarm-0.1.1743371918}/src/swarm/utils/color_utils.py +0 -0
- {open_swarm-0.1.1743371228 → open_swarm-0.1.1743371918}/src/swarm/utils/context_utils.py +0 -0
- {open_swarm-0.1.1743371228 → open_swarm-0.1.1743371918}/src/swarm/utils/general_utils.py +0 -0
- {open_swarm-0.1.1743371228 → open_swarm-0.1.1743371918}/src/swarm/utils/log_utils.py +0 -0
- {open_swarm-0.1.1743371228 → open_swarm-0.1.1743371918}/src/swarm/utils/logger.py +0 -0
- {open_swarm-0.1.1743371228 → open_swarm-0.1.1743371918}/src/swarm/utils/logger_setup.py +0 -0
- {open_swarm-0.1.1743371228 → open_swarm-0.1.1743371918}/src/swarm/utils/message_sequence.py +0 -0
- {open_swarm-0.1.1743371228 → open_swarm-0.1.1743371918}/src/swarm/utils/message_utils.py +0 -0
- {open_swarm-0.1.1743371228 → open_swarm-0.1.1743371918}/src/swarm/utils/redact.py +0 -0
- {open_swarm-0.1.1743371228 → open_swarm-0.1.1743371918}/src/swarm/views/__init__.py +0 -0
- {open_swarm-0.1.1743371228 → open_swarm-0.1.1743371918}/src/swarm/views/api_views.py +0 -0
- {open_swarm-0.1.1743371228 → open_swarm-0.1.1743371918}/src/swarm/views/chat_views.py +0 -0
- {open_swarm-0.1.1743371228 → open_swarm-0.1.1743371918}/src/swarm/views/core_views.py +0 -0
- {open_swarm-0.1.1743371228 → open_swarm-0.1.1743371918}/src/swarm/views/message_views.py +0 -0
- {open_swarm-0.1.1743371228 → open_swarm-0.1.1743371918}/src/swarm/views/model_views.py +0 -0
- {open_swarm-0.1.1743371228 → open_swarm-0.1.1743371918}/src/swarm/views/utils.py +0 -0
- {open_swarm-0.1.1743371228 → open_swarm-0.1.1743371918}/src/swarm/views/web_views.py +0 -0
- {open_swarm-0.1.1743371228 → open_swarm-0.1.1743371918}/src/swarm/wsgi.py +0 -0
- {open_swarm-0.1.1743371228 → open_swarm-0.1.1743371918}/tests/__init__.py +0 -0
- {open_swarm-0.1.1743371228 → open_swarm-0.1.1743371918}/tests/api/conftest.py +0 -0
- {open_swarm-0.1.1743371228 → open_swarm-0.1.1743371918}/tests/api/test_chat_completions_auth_async.py +0 -0
- {open_swarm-0.1.1743371228 → open_swarm-0.1.1743371918}/tests/api/test_chat_completions_failing_async.py +0 -0
- {open_swarm-0.1.1743371228 → open_swarm-0.1.1743371918}/tests/api/test_chat_completions_validation_async.py +0 -0
- {open_swarm-0.1.1743371228 → open_swarm-0.1.1743371918}/tests/blueprints/test_burnt_noodles.py +0 -0
- {open_swarm-0.1.1743371228 → open_swarm-0.1.1743371918}/tests/blueprints/test_chatbot.py +0 -0
- {open_swarm-0.1.1743371228 → open_swarm-0.1.1743371918}/tests/blueprints/test_digitalbutlers.py +0 -0
- {open_swarm-0.1.1743371228 → open_swarm-0.1.1743371918}/tests/blueprints/test_dilbot_universe.py +0 -0
- {open_swarm-0.1.1743371228 → open_swarm-0.1.1743371918}/tests/blueprints/test_divine_code.py +0 -0
- {open_swarm-0.1.1743371228 → open_swarm-0.1.1743371918}/tests/blueprints/test_family_ties.py +0 -0
- {open_swarm-0.1.1743371228 → open_swarm-0.1.1743371918}/tests/blueprints/test_gaggle.py +0 -0
- {open_swarm-0.1.1743371228 → open_swarm-0.1.1743371918}/tests/blueprints/test_gotchaman.py +0 -0
- {open_swarm-0.1.1743371228 → open_swarm-0.1.1743371918}/tests/blueprints/test_mcp_demo.py +0 -0
- {open_swarm-0.1.1743371228 → open_swarm-0.1.1743371918}/tests/blueprints/test_mission_improbable.py +0 -0
- {open_swarm-0.1.1743371228 → open_swarm-0.1.1743371918}/tests/blueprints/test_monkai_magic.py +0 -0
- {open_swarm-0.1.1743371228 → open_swarm-0.1.1743371918}/tests/blueprints/test_nebula_shellz.py +0 -0
- {open_swarm-0.1.1743371228 → open_swarm-0.1.1743371918}/tests/blueprints/test_omniplex.py +0 -0
- {open_swarm-0.1.1743371228 → open_swarm-0.1.1743371918}/tests/blueprints/test_suggestion.py +0 -0
- {open_swarm-0.1.1743371228 → open_swarm-0.1.1743371918}/tests/blueprints/test_unapologetic_press.py +0 -0
- {open_swarm-0.1.1743371228 → open_swarm-0.1.1743371918}/tests/blueprints/test_whiskeytangofoxtrot.py +0 -0
- {open_swarm-0.1.1743371228 → open_swarm-0.1.1743371918}/tests/cli/test_list_blueprints.py +0 -0
- {open_swarm-0.1.1743371228 → open_swarm-0.1.1743371918}/tests/conftest.py +0 -0
- {open_swarm-0.1.1743371228 → open_swarm-0.1.1743371918}/tests/swarm_config.json +0 -0
- {open_swarm-0.1.1743371228 → open_swarm-0.1.1743371918}/tests/system/test_burnt_noodles.sh +0 -0
- {open_swarm-0.1.1743371228 → open_swarm-0.1.1743371918}/tests/system/test_chucks_angels.sh +0 -0
- {open_swarm-0.1.1743371228 → open_swarm-0.1.1743371918}/tests/system/test_digitalbutlers.sh +0 -0
- {open_swarm-0.1.1743371228 → open_swarm-0.1.1743371918}/tests/system/test_dilbot_universe.sh +0 -0
- {open_swarm-0.1.1743371228 → open_swarm-0.1.1743371918}/tests/system/test_divine_code.sh +0 -0
- {open_swarm-0.1.1743371228 → open_swarm-0.1.1743371918}/tests/system/test_django_chat.sh +0 -0
- {open_swarm-0.1.1743371228 → open_swarm-0.1.1743371918}/tests/system/test_echocraft.sh +0 -0
- {open_swarm-0.1.1743371228 → open_swarm-0.1.1743371918}/tests/system/test_family_ties.sh +0 -0
- {open_swarm-0.1.1743371228 → open_swarm-0.1.1743371918}/tests/system/test_flock.sh +0 -0
- {open_swarm-0.1.1743371228 → open_swarm-0.1.1743371918}/tests/system/test_gaggle.sh +0 -0
- {open_swarm-0.1.1743371228 → open_swarm-0.1.1743371918}/tests/system/test_gotchaman.sh +0 -0
- {open_swarm-0.1.1743371228 → open_swarm-0.1.1743371918}/tests/system/test_monkai-magic.sh +0 -0
- {open_swarm-0.1.1743371228 → open_swarm-0.1.1743371918}/tests/system/test_nebula_shellz.sh +0 -0
- {open_swarm-0.1.1743371228 → open_swarm-0.1.1743371918}/tests/system/test_omniplex.sh +0 -0
- {open_swarm-0.1.1743371228 → open_swarm-0.1.1743371918}/tests/system/test_rue-code.sh +0 -0
- {open_swarm-0.1.1743371228 → open_swarm-0.1.1743371918}/tests/system/test_suggestion.sh +0 -0
- {open_swarm-0.1.1743371228 → open_swarm-0.1.1743371918}/tests/system/test_unapologetic_press.sh +0 -0
- {open_swarm-0.1.1743371228 → open_swarm-0.1.1743371918}/tests/system/test_university.sh +0 -0
- {open_swarm-0.1.1743371228 → open_swarm-0.1.1743371918}/tests/system/test_whiskeytango_foxtrot.sh +0 -0
- {open_swarm-0.1.1743371228 → open_swarm-0.1.1743371918}/tests/test_blueprint_loading.py +0 -0
- {open_swarm-0.1.1743371228 → open_swarm-0.1.1743371918}/tests/test_cli_mode_selection.py +0 -0
- {open_swarm-0.1.1743371228 → open_swarm-0.1.1743371918}/tests/test_core_filter_duplicate_system_messages.py +0 -0
- {open_swarm-0.1.1743371228 → open_swarm-0.1.1743371918}/tests/test_core_filter_messages.py +0 -0
- {open_swarm-0.1.1743371228 → open_swarm-0.1.1743371918}/tests/test_core_truncate_message_history.py +0 -0
- {open_swarm-0.1.1743371228 → open_swarm-0.1.1743371918}/tests/test_core_update_null_content.py +0 -0
- {open_swarm-0.1.1743371228 → open_swarm-0.1.1743371918}/tests/test_dummy.py +0 -0
- {open_swarm-0.1.1743371228 → open_swarm-0.1.1743371918}/tests/test_truncate_message_history.py +0 -0
- {open_swarm-0.1.1743371228 → open_swarm-0.1.1743371918}/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.
|
3
|
+
Version: 0.1.1743371918
|
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
|
@@ -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
|
-
|