open-swarm 0.1.1743416034__tar.gz → 0.1.1743449197__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.1743416034 → open_swarm-0.1.1743449197}/PKG-INFO +1 -1
- {open_swarm-0.1.1743416034 → open_swarm-0.1.1743449197}/pyproject.toml +1 -1
- open_swarm-0.1.1743449197/src/swarm/blueprints/burnt_noodles/blueprint_burnt_noodles.py +304 -0
- open_swarm-0.1.1743449197/src/swarm/extensions/blueprint/runnable_blueprint.py +42 -0
- {open_swarm-0.1.1743416034 → open_swarm-0.1.1743449197}/tests/blueprints/test_burnt_noodles.py +52 -84
- {open_swarm-0.1.1743416034 → open_swarm-0.1.1743449197}/tests/extensions/launchers/test_swarm_api_launcher.py +6 -3
- open_swarm-0.1.1743416034/src/swarm/blueprints/burnt_noodles/blueprint_burnt_noodles.py +0 -412
- {open_swarm-0.1.1743416034 → open_swarm-0.1.1743449197}/.gitignore +0 -0
- {open_swarm-0.1.1743416034 → open_swarm-0.1.1743449197}/LICENSE +0 -0
- {open_swarm-0.1.1743416034 → open_swarm-0.1.1743449197}/README.md +0 -0
- {open_swarm-0.1.1743416034 → open_swarm-0.1.1743449197}/src/swarm/__init__.py +0 -0
- {open_swarm-0.1.1743416034 → open_swarm-0.1.1743449197}/src/swarm/agent/__init__.py +0 -0
- {open_swarm-0.1.1743416034 → open_swarm-0.1.1743449197}/src/swarm/apps.py +0 -0
- {open_swarm-0.1.1743416034 → open_swarm-0.1.1743449197}/src/swarm/auth.py +0 -0
- {open_swarm-0.1.1743416034 → open_swarm-0.1.1743449197}/src/swarm/blueprints/README.md +0 -0
- {open_swarm-0.1.1743416034 → open_swarm-0.1.1743449197}/src/swarm/blueprints/chatbot/blueprint_chatbot.py +0 -0
- {open_swarm-0.1.1743416034 → open_swarm-0.1.1743449197}/src/swarm/blueprints/chatbot/templates/chatbot/chatbot.html +0 -0
- {open_swarm-0.1.1743416034 → open_swarm-0.1.1743449197}/src/swarm/blueprints/digitalbutlers/blueprint_digitalbutlers.py +0 -0
- {open_swarm-0.1.1743416034 → open_swarm-0.1.1743449197}/src/swarm/blueprints/dilbot_universe/blueprint_dilbot_universe.py +0 -0
- {open_swarm-0.1.1743416034 → open_swarm-0.1.1743449197}/src/swarm/blueprints/divine_code/__init__.py +0 -0
- {open_swarm-0.1.1743416034 → open_swarm-0.1.1743449197}/src/swarm/blueprints/divine_code/apps.py +0 -0
- {open_swarm-0.1.1743416034 → open_swarm-0.1.1743449197}/src/swarm/blueprints/divine_code/blueprint_divine_code.py +0 -0
- {open_swarm-0.1.1743416034 → open_swarm-0.1.1743449197}/src/swarm/blueprints/django_chat/apps.py +0 -0
- {open_swarm-0.1.1743416034 → open_swarm-0.1.1743449197}/src/swarm/blueprints/django_chat/blueprint_django_chat.py +0 -0
- {open_swarm-0.1.1743416034 → open_swarm-0.1.1743449197}/src/swarm/blueprints/django_chat/templates/django_chat/django_chat_webpage.html +0 -0
- {open_swarm-0.1.1743416034 → open_swarm-0.1.1743449197}/src/swarm/blueprints/django_chat/urls.py +0 -0
- {open_swarm-0.1.1743416034 → open_swarm-0.1.1743449197}/src/swarm/blueprints/django_chat/views.py +0 -0
- {open_swarm-0.1.1743416034 → open_swarm-0.1.1743449197}/src/swarm/blueprints/echocraft/blueprint_echocraft.py +0 -0
- {open_swarm-0.1.1743416034 → open_swarm-0.1.1743449197}/src/swarm/blueprints/family_ties/apps.py +0 -0
- {open_swarm-0.1.1743416034 → open_swarm-0.1.1743449197}/src/swarm/blueprints/family_ties/blueprint_family_ties.py +0 -0
- {open_swarm-0.1.1743416034 → open_swarm-0.1.1743449197}/src/swarm/blueprints/family_ties/models.py +0 -0
- {open_swarm-0.1.1743416034 → open_swarm-0.1.1743449197}/src/swarm/blueprints/family_ties/serializers.py +0 -0
- {open_swarm-0.1.1743416034 → open_swarm-0.1.1743449197}/src/swarm/blueprints/family_ties/settings.py +0 -0
- {open_swarm-0.1.1743416034 → open_swarm-0.1.1743449197}/src/swarm/blueprints/family_ties/urls.py +0 -0
- {open_swarm-0.1.1743416034 → open_swarm-0.1.1743449197}/src/swarm/blueprints/family_ties/views.py +0 -0
- {open_swarm-0.1.1743416034 → open_swarm-0.1.1743449197}/src/swarm/blueprints/flock/__init__.py +0 -0
- {open_swarm-0.1.1743416034 → open_swarm-0.1.1743449197}/src/swarm/blueprints/gaggle/blueprint_gaggle.py +0 -0
- {open_swarm-0.1.1743416034 → open_swarm-0.1.1743449197}/src/swarm/blueprints/gotchaman/blueprint_gotchaman.py +0 -0
- {open_swarm-0.1.1743416034 → open_swarm-0.1.1743449197}/src/swarm/blueprints/mcp_demo/blueprint_mcp_demo.py +0 -0
- {open_swarm-0.1.1743416034 → open_swarm-0.1.1743449197}/src/swarm/blueprints/messenger/templates/messenger/messenger.html +0 -0
- {open_swarm-0.1.1743416034 → open_swarm-0.1.1743449197}/src/swarm/blueprints/mission_improbable/blueprint_mission_improbable.py +0 -0
- {open_swarm-0.1.1743416034 → open_swarm-0.1.1743449197}/src/swarm/blueprints/monkai_magic/blueprint_monkai_magic.py +0 -0
- {open_swarm-0.1.1743416034 → open_swarm-0.1.1743449197}/src/swarm/blueprints/nebula_shellz/blueprint_nebula_shellz.py +0 -0
- {open_swarm-0.1.1743416034 → open_swarm-0.1.1743449197}/src/swarm/blueprints/omniplex/blueprint_omniplex.py +0 -0
- {open_swarm-0.1.1743416034 → open_swarm-0.1.1743449197}/src/swarm/blueprints/rue_code/__init__.py +0 -0
- {open_swarm-0.1.1743416034 → open_swarm-0.1.1743449197}/src/swarm/blueprints/rue_code/blueprint_rue_code.py +0 -0
- {open_swarm-0.1.1743416034 → open_swarm-0.1.1743449197}/src/swarm/blueprints/suggestion/blueprint_suggestion.py +0 -0
- {open_swarm-0.1.1743416034 → open_swarm-0.1.1743449197}/src/swarm/blueprints/unapologetic_press/blueprint_unapologetic_press.py +0 -0
- {open_swarm-0.1.1743416034 → open_swarm-0.1.1743449197}/src/swarm/blueprints/whiskeytango_foxtrot/__init__.py +0 -0
- {open_swarm-0.1.1743416034 → open_swarm-0.1.1743449197}/src/swarm/blueprints/whiskeytango_foxtrot/apps.py +0 -0
- {open_swarm-0.1.1743416034 → open_swarm-0.1.1743449197}/src/swarm/blueprints/whiskeytango_foxtrot/blueprint_whiskeytango_foxtrot.py +0 -0
- {open_swarm-0.1.1743416034 → open_swarm-0.1.1743449197}/src/swarm/consumers.py +0 -0
- {open_swarm-0.1.1743416034 → open_swarm-0.1.1743449197}/src/swarm/extensions/__init__.py +0 -0
- {open_swarm-0.1.1743416034 → open_swarm-0.1.1743449197}/src/swarm/extensions/blueprint/__init__.py +0 -0
- {open_swarm-0.1.1743416034 → open_swarm-0.1.1743449197}/src/swarm/extensions/blueprint/agent_utils.py +0 -0
- {open_swarm-0.1.1743416034 → open_swarm-0.1.1743449197}/src/swarm/extensions/blueprint/blueprint_base.py +0 -0
- {open_swarm-0.1.1743416034 → open_swarm-0.1.1743449197}/src/swarm/extensions/blueprint/blueprint_discovery.py +0 -0
- {open_swarm-0.1.1743416034 → open_swarm-0.1.1743449197}/src/swarm/extensions/blueprint/blueprint_utils.py +0 -0
- {open_swarm-0.1.1743416034 → open_swarm-0.1.1743449197}/src/swarm/extensions/blueprint/cli_handler.py +0 -0
- {open_swarm-0.1.1743416034 → open_swarm-0.1.1743449197}/src/swarm/extensions/blueprint/common_utils.py +0 -0
- {open_swarm-0.1.1743416034 → open_swarm-0.1.1743449197}/src/swarm/extensions/blueprint/config_loader.py +0 -0
- {open_swarm-0.1.1743416034 → open_swarm-0.1.1743449197}/src/swarm/extensions/blueprint/django_utils.py +0 -0
- {open_swarm-0.1.1743416034 → open_swarm-0.1.1743449197}/src/swarm/extensions/blueprint/interactive_mode.py +0 -0
- {open_swarm-0.1.1743416034 → open_swarm-0.1.1743449197}/src/swarm/extensions/blueprint/modes/rest_mode.py +0 -0
- {open_swarm-0.1.1743416034 → open_swarm-0.1.1743449197}/src/swarm/extensions/blueprint/output_utils.py +0 -0
- {open_swarm-0.1.1743416034 → open_swarm-0.1.1743449197}/src/swarm/extensions/blueprint/spinner.py +0 -0
- {open_swarm-0.1.1743416034 → open_swarm-0.1.1743449197}/src/swarm/extensions/cli/__init__.py +0 -0
- {open_swarm-0.1.1743416034 → open_swarm-0.1.1743449197}/src/swarm/extensions/cli/blueprint_runner.py +0 -0
- {open_swarm-0.1.1743416034 → open_swarm-0.1.1743449197}/src/swarm/extensions/cli/cli_args.py +0 -0
- {open_swarm-0.1.1743416034 → open_swarm-0.1.1743449197}/src/swarm/extensions/cli/commands/__init__.py +0 -0
- {open_swarm-0.1.1743416034 → open_swarm-0.1.1743449197}/src/swarm/extensions/cli/commands/blueprint_management.py +0 -0
- {open_swarm-0.1.1743416034 → open_swarm-0.1.1743449197}/src/swarm/extensions/cli/commands/config_management.py +0 -0
- {open_swarm-0.1.1743416034 → open_swarm-0.1.1743449197}/src/swarm/extensions/cli/commands/edit_config.py +0 -0
- {open_swarm-0.1.1743416034 → open_swarm-0.1.1743449197}/src/swarm/extensions/cli/commands/list_blueprints.py +0 -0
- {open_swarm-0.1.1743416034 → open_swarm-0.1.1743449197}/src/swarm/extensions/cli/commands/validate_env.py +0 -0
- {open_swarm-0.1.1743416034 → open_swarm-0.1.1743449197}/src/swarm/extensions/cli/commands/validate_envvars.py +0 -0
- {open_swarm-0.1.1743416034 → open_swarm-0.1.1743449197}/src/swarm/extensions/cli/interactive_shell.py +0 -0
- {open_swarm-0.1.1743416034 → open_swarm-0.1.1743449197}/src/swarm/extensions/cli/main.py +0 -0
- {open_swarm-0.1.1743416034 → open_swarm-0.1.1743449197}/src/swarm/extensions/cli/selection.py +0 -0
- {open_swarm-0.1.1743416034 → open_swarm-0.1.1743449197}/src/swarm/extensions/cli/utils/discover_commands.py +0 -0
- {open_swarm-0.1.1743416034 → open_swarm-0.1.1743449197}/src/swarm/extensions/cli/utils/env_setup.py +0 -0
- {open_swarm-0.1.1743416034 → open_swarm-0.1.1743449197}/src/swarm/extensions/cli/utils.py +0 -0
- {open_swarm-0.1.1743416034 → open_swarm-0.1.1743449197}/src/swarm/extensions/config/__init__.py +0 -0
- {open_swarm-0.1.1743416034 → open_swarm-0.1.1743449197}/src/swarm/extensions/config/config_loader.py +0 -0
- {open_swarm-0.1.1743416034 → open_swarm-0.1.1743449197}/src/swarm/extensions/config/config_manager.py +0 -0
- {open_swarm-0.1.1743416034 → open_swarm-0.1.1743449197}/src/swarm/extensions/config/server_config.py +0 -0
- {open_swarm-0.1.1743416034 → open_swarm-0.1.1743449197}/src/swarm/extensions/config/setup_wizard.py +0 -0
- {open_swarm-0.1.1743416034 → open_swarm-0.1.1743449197}/src/swarm/extensions/config/utils/__init__.py +0 -0
- {open_swarm-0.1.1743416034 → open_swarm-0.1.1743449197}/src/swarm/extensions/config/utils/logger.py +0 -0
- {open_swarm-0.1.1743416034 → open_swarm-0.1.1743449197}/src/swarm/extensions/launchers/__init__.py +0 -0
- {open_swarm-0.1.1743416034 → open_swarm-0.1.1743449197}/src/swarm/extensions/launchers/build_launchers.py +0 -0
- {open_swarm-0.1.1743416034 → open_swarm-0.1.1743449197}/src/swarm/extensions/launchers/build_swarm_wrapper.py +0 -0
- {open_swarm-0.1.1743416034 → open_swarm-0.1.1743449197}/src/swarm/extensions/launchers/swarm_api.py +0 -0
- {open_swarm-0.1.1743416034 → open_swarm-0.1.1743449197}/src/swarm/extensions/launchers/swarm_cli.py +0 -0
- {open_swarm-0.1.1743416034 → open_swarm-0.1.1743449197}/src/swarm/extensions/launchers/swarm_wrapper.py +0 -0
- {open_swarm-0.1.1743416034 → open_swarm-0.1.1743449197}/src/swarm/llm/chat_completion.py +0 -0
- {open_swarm-0.1.1743416034 → open_swarm-0.1.1743449197}/src/swarm/management/__init__.py +0 -0
- {open_swarm-0.1.1743416034 → open_swarm-0.1.1743449197}/src/swarm/management/commands/__init__.py +0 -0
- {open_swarm-0.1.1743416034 → open_swarm-0.1.1743449197}/src/swarm/management/commands/runserver.py +0 -0
- {open_swarm-0.1.1743416034 → open_swarm-0.1.1743449197}/src/swarm/messages.py +0 -0
- {open_swarm-0.1.1743416034 → open_swarm-0.1.1743449197}/src/swarm/middleware.py +0 -0
- {open_swarm-0.1.1743416034 → open_swarm-0.1.1743449197}/src/swarm/migrations/0010_initial_chat_models.py +0 -0
- {open_swarm-0.1.1743416034 → open_swarm-0.1.1743449197}/src/swarm/migrations/__init__.py +0 -0
- {open_swarm-0.1.1743416034 → open_swarm-0.1.1743449197}/src/swarm/models.py +0 -0
- {open_swarm-0.1.1743416034 → open_swarm-0.1.1743449197}/src/swarm/permissions.py +0 -0
- {open_swarm-0.1.1743416034 → open_swarm-0.1.1743449197}/src/swarm/repl/__init__.py +0 -0
- {open_swarm-0.1.1743416034 → open_swarm-0.1.1743449197}/src/swarm/repl/repl.py +0 -0
- {open_swarm-0.1.1743416034 → open_swarm-0.1.1743449197}/src/swarm/serializers.py +0 -0
- {open_swarm-0.1.1743416034 → open_swarm-0.1.1743449197}/src/swarm/settings.py +0 -0
- {open_swarm-0.1.1743416034 → open_swarm-0.1.1743449197}/src/swarm/static/contrib/fonts/fontawesome-webfont.ttf +0 -0
- {open_swarm-0.1.1743416034 → open_swarm-0.1.1743449197}/src/swarm/static/contrib/fonts/fontawesome-webfont.woff +0 -0
- {open_swarm-0.1.1743416034 → open_swarm-0.1.1743449197}/src/swarm/static/contrib/fonts/fontawesome-webfont.woff2 +0 -0
- {open_swarm-0.1.1743416034 → open_swarm-0.1.1743449197}/src/swarm/static/contrib/markedjs/marked.min.js +0 -0
- {open_swarm-0.1.1743416034 → open_swarm-0.1.1743449197}/src/swarm/static/contrib/tabler-icons/adjustments-horizontal.svg +0 -0
- {open_swarm-0.1.1743416034 → open_swarm-0.1.1743449197}/src/swarm/static/contrib/tabler-icons/alert-triangle.svg +0 -0
- {open_swarm-0.1.1743416034 → open_swarm-0.1.1743449197}/src/swarm/static/contrib/tabler-icons/archive.svg +0 -0
- {open_swarm-0.1.1743416034 → open_swarm-0.1.1743449197}/src/swarm/static/contrib/tabler-icons/artboard.svg +0 -0
- {open_swarm-0.1.1743416034 → open_swarm-0.1.1743449197}/src/swarm/static/contrib/tabler-icons/automatic-gearbox.svg +0 -0
- {open_swarm-0.1.1743416034 → open_swarm-0.1.1743449197}/src/swarm/static/contrib/tabler-icons/box-multiple.svg +0 -0
- {open_swarm-0.1.1743416034 → open_swarm-0.1.1743449197}/src/swarm/static/contrib/tabler-icons/carambola.svg +0 -0
- {open_swarm-0.1.1743416034 → open_swarm-0.1.1743449197}/src/swarm/static/contrib/tabler-icons/copy.svg +0 -0
- {open_swarm-0.1.1743416034 → open_swarm-0.1.1743449197}/src/swarm/static/contrib/tabler-icons/download.svg +0 -0
- {open_swarm-0.1.1743416034 → open_swarm-0.1.1743449197}/src/swarm/static/contrib/tabler-icons/edit.svg +0 -0
- {open_swarm-0.1.1743416034 → open_swarm-0.1.1743449197}/src/swarm/static/contrib/tabler-icons/filled/carambola.svg +0 -0
- {open_swarm-0.1.1743416034 → open_swarm-0.1.1743449197}/src/swarm/static/contrib/tabler-icons/filled/paint.svg +0 -0
- {open_swarm-0.1.1743416034 → open_swarm-0.1.1743449197}/src/swarm/static/contrib/tabler-icons/headset.svg +0 -0
- {open_swarm-0.1.1743416034 → open_swarm-0.1.1743449197}/src/swarm/static/contrib/tabler-icons/layout-sidebar-left-collapse.svg +0 -0
- {open_swarm-0.1.1743416034 → open_swarm-0.1.1743449197}/src/swarm/static/contrib/tabler-icons/layout-sidebar-left-expand.svg +0 -0
- {open_swarm-0.1.1743416034 → open_swarm-0.1.1743449197}/src/swarm/static/contrib/tabler-icons/layout-sidebar-right-collapse.svg +0 -0
- {open_swarm-0.1.1743416034 → open_swarm-0.1.1743449197}/src/swarm/static/contrib/tabler-icons/layout-sidebar-right-expand.svg +0 -0
- {open_swarm-0.1.1743416034 → open_swarm-0.1.1743449197}/src/swarm/static/contrib/tabler-icons/message-chatbot.svg +0 -0
- {open_swarm-0.1.1743416034 → open_swarm-0.1.1743449197}/src/swarm/static/contrib/tabler-icons/message-star.svg +0 -0
- {open_swarm-0.1.1743416034 → open_swarm-0.1.1743449197}/src/swarm/static/contrib/tabler-icons/message-x.svg +0 -0
- {open_swarm-0.1.1743416034 → open_swarm-0.1.1743449197}/src/swarm/static/contrib/tabler-icons/message.svg +0 -0
- {open_swarm-0.1.1743416034 → open_swarm-0.1.1743449197}/src/swarm/static/contrib/tabler-icons/paperclip.svg +0 -0
- {open_swarm-0.1.1743416034 → open_swarm-0.1.1743449197}/src/swarm/static/contrib/tabler-icons/playlist-add.svg +0 -0
- {open_swarm-0.1.1743416034 → open_swarm-0.1.1743449197}/src/swarm/static/contrib/tabler-icons/robot.svg +0 -0
- {open_swarm-0.1.1743416034 → open_swarm-0.1.1743449197}/src/swarm/static/contrib/tabler-icons/search.svg +0 -0
- {open_swarm-0.1.1743416034 → open_swarm-0.1.1743449197}/src/swarm/static/contrib/tabler-icons/settings.svg +0 -0
- {open_swarm-0.1.1743416034 → open_swarm-0.1.1743449197}/src/swarm/static/contrib/tabler-icons/thumb-down.svg +0 -0
- {open_swarm-0.1.1743416034 → open_swarm-0.1.1743449197}/src/swarm/static/contrib/tabler-icons/thumb-up.svg +0 -0
- {open_swarm-0.1.1743416034 → open_swarm-0.1.1743449197}/src/swarm/static/css/dropdown.css +0 -0
- {open_swarm-0.1.1743416034 → open_swarm-0.1.1743449197}/src/swarm/static/htmx/htmx.min.js +0 -0
- {open_swarm-0.1.1743416034 → open_swarm-0.1.1743449197}/src/swarm/static/js/dropdown.js +0 -0
- {open_swarm-0.1.1743416034 → open_swarm-0.1.1743449197}/src/swarm/static/rest_mode/css/base.css +0 -0
- {open_swarm-0.1.1743416034 → open_swarm-0.1.1743449197}/src/swarm/static/rest_mode/css/chat-history.css +0 -0
- {open_swarm-0.1.1743416034 → open_swarm-0.1.1743449197}/src/swarm/static/rest_mode/css/chat.css +0 -0
- {open_swarm-0.1.1743416034 → open_swarm-0.1.1743449197}/src/swarm/static/rest_mode/css/chatbot.css +0 -0
- {open_swarm-0.1.1743416034 → open_swarm-0.1.1743449197}/src/swarm/static/rest_mode/css/chatgpt.css +0 -0
- {open_swarm-0.1.1743416034 → open_swarm-0.1.1743449197}/src/swarm/static/rest_mode/css/colors/corporate.css +0 -0
- {open_swarm-0.1.1743416034 → open_swarm-0.1.1743449197}/src/swarm/static/rest_mode/css/colors/pastel.css +0 -0
- {open_swarm-0.1.1743416034 → open_swarm-0.1.1743449197}/src/swarm/static/rest_mode/css/colors/tropical.css +0 -0
- {open_swarm-0.1.1743416034 → open_swarm-0.1.1743449197}/src/swarm/static/rest_mode/css/general.css +0 -0
- {open_swarm-0.1.1743416034 → open_swarm-0.1.1743449197}/src/swarm/static/rest_mode/css/layout.css +0 -0
- {open_swarm-0.1.1743416034 → open_swarm-0.1.1743449197}/src/swarm/static/rest_mode/css/layouts/messenger-layout.css +0 -0
- {open_swarm-0.1.1743416034 → open_swarm-0.1.1743449197}/src/swarm/static/rest_mode/css/layouts/minimalist-layout.css +0 -0
- {open_swarm-0.1.1743416034 → open_swarm-0.1.1743449197}/src/swarm/static/rest_mode/css/layouts/mobile-layout.css +0 -0
- {open_swarm-0.1.1743416034 → open_swarm-0.1.1743449197}/src/swarm/static/rest_mode/css/messages.css +0 -0
- {open_swarm-0.1.1743416034 → open_swarm-0.1.1743449197}/src/swarm/static/rest_mode/css/messenger.css +0 -0
- {open_swarm-0.1.1743416034 → open_swarm-0.1.1743449197}/src/swarm/static/rest_mode/css/settings.css +0 -0
- {open_swarm-0.1.1743416034 → open_swarm-0.1.1743449197}/src/swarm/static/rest_mode/css/simple.css +0 -0
- {open_swarm-0.1.1743416034 → open_swarm-0.1.1743449197}/src/swarm/static/rest_mode/css/slack.css +0 -0
- {open_swarm-0.1.1743416034 → open_swarm-0.1.1743449197}/src/swarm/static/rest_mode/css/style.css +0 -0
- {open_swarm-0.1.1743416034 → open_swarm-0.1.1743449197}/src/swarm/static/rest_mode/css/theme.css +0 -0
- {open_swarm-0.1.1743416034 → open_swarm-0.1.1743449197}/src/swarm/static/rest_mode/css/toast.css +0 -0
- {open_swarm-0.1.1743416034 → open_swarm-0.1.1743449197}/src/swarm/static/rest_mode/js/auth.js +0 -0
- {open_swarm-0.1.1743416034 → open_swarm-0.1.1743449197}/src/swarm/static/rest_mode/js/blueprint.js +0 -0
- {open_swarm-0.1.1743416034 → open_swarm-0.1.1743449197}/src/swarm/static/rest_mode/js/blueprintUtils.js +0 -0
- {open_swarm-0.1.1743416034 → open_swarm-0.1.1743449197}/src/swarm/static/rest_mode/js/chatLogic.js +0 -0
- {open_swarm-0.1.1743416034 → open_swarm-0.1.1743449197}/src/swarm/static/rest_mode/js/debug.js +0 -0
- {open_swarm-0.1.1743416034 → open_swarm-0.1.1743449197}/src/swarm/static/rest_mode/js/events.js +0 -0
- {open_swarm-0.1.1743416034 → open_swarm-0.1.1743449197}/src/swarm/static/rest_mode/js/main.js +0 -0
- {open_swarm-0.1.1743416034 → open_swarm-0.1.1743449197}/src/swarm/static/rest_mode/js/messages.js +0 -0
- {open_swarm-0.1.1743416034 → open_swarm-0.1.1743449197}/src/swarm/static/rest_mode/js/messengerLogic.js +0 -0
- {open_swarm-0.1.1743416034 → open_swarm-0.1.1743449197}/src/swarm/static/rest_mode/js/modules/apiService.js +0 -0
- {open_swarm-0.1.1743416034 → open_swarm-0.1.1743449197}/src/swarm/static/rest_mode/js/modules/blueprintManager.js +0 -0
- {open_swarm-0.1.1743416034 → open_swarm-0.1.1743449197}/src/swarm/static/rest_mode/js/modules/chatHistory.js +0 -0
- {open_swarm-0.1.1743416034 → open_swarm-0.1.1743449197}/src/swarm/static/rest_mode/js/modules/debugLogger.js +0 -0
- {open_swarm-0.1.1743416034 → open_swarm-0.1.1743449197}/src/swarm/static/rest_mode/js/modules/eventHandlers.js +0 -0
- {open_swarm-0.1.1743416034 → open_swarm-0.1.1743449197}/src/swarm/static/rest_mode/js/modules/messageProcessor.js +0 -0
- {open_swarm-0.1.1743416034 → open_swarm-0.1.1743449197}/src/swarm/static/rest_mode/js/modules/state.js +0 -0
- {open_swarm-0.1.1743416034 → open_swarm-0.1.1743449197}/src/swarm/static/rest_mode/js/modules/userInteractions.js +0 -0
- {open_swarm-0.1.1743416034 → open_swarm-0.1.1743449197}/src/swarm/static/rest_mode/js/modules/validation.js +0 -0
- {open_swarm-0.1.1743416034 → open_swarm-0.1.1743449197}/src/swarm/static/rest_mode/js/rendering.js +0 -0
- {open_swarm-0.1.1743416034 → open_swarm-0.1.1743449197}/src/swarm/static/rest_mode/js/settings.js +0 -0
- {open_swarm-0.1.1743416034 → open_swarm-0.1.1743449197}/src/swarm/static/rest_mode/js/sidebar.js +0 -0
- {open_swarm-0.1.1743416034 → open_swarm-0.1.1743449197}/src/swarm/static/rest_mode/js/simpleLogic.js +0 -0
- {open_swarm-0.1.1743416034 → open_swarm-0.1.1743449197}/src/swarm/static/rest_mode/js/slackLogic.js +0 -0
- {open_swarm-0.1.1743416034 → open_swarm-0.1.1743449197}/src/swarm/static/rest_mode/js/splash.js +0 -0
- {open_swarm-0.1.1743416034 → open_swarm-0.1.1743449197}/src/swarm/static/rest_mode/js/theme.js +0 -0
- {open_swarm-0.1.1743416034 → open_swarm-0.1.1743449197}/src/swarm/static/rest_mode/js/toast.js +0 -0
- {open_swarm-0.1.1743416034 → open_swarm-0.1.1743449197}/src/swarm/static/rest_mode/js/ui.js +0 -0
- {open_swarm-0.1.1743416034 → open_swarm-0.1.1743449197}/src/swarm/static/rest_mode/js/validation.js +0 -0
- {open_swarm-0.1.1743416034 → open_swarm-0.1.1743449197}/src/swarm/static/rest_mode/svg/animated_spinner.svg +0 -0
- {open_swarm-0.1.1743416034 → open_swarm-0.1.1743449197}/src/swarm/static/rest_mode/svg/arrow_down.svg +0 -0
- {open_swarm-0.1.1743416034 → open_swarm-0.1.1743449197}/src/swarm/static/rest_mode/svg/arrow_left.svg +0 -0
- {open_swarm-0.1.1743416034 → open_swarm-0.1.1743449197}/src/swarm/static/rest_mode/svg/arrow_right.svg +0 -0
- {open_swarm-0.1.1743416034 → open_swarm-0.1.1743449197}/src/swarm/static/rest_mode/svg/arrow_up.svg +0 -0
- {open_swarm-0.1.1743416034 → open_swarm-0.1.1743449197}/src/swarm/static/rest_mode/svg/attach.svg +0 -0
- {open_swarm-0.1.1743416034 → open_swarm-0.1.1743449197}/src/swarm/static/rest_mode/svg/avatar.svg +0 -0
- {open_swarm-0.1.1743416034 → open_swarm-0.1.1743449197}/src/swarm/static/rest_mode/svg/canvas.svg +0 -0
- {open_swarm-0.1.1743416034 → open_swarm-0.1.1743449197}/src/swarm/static/rest_mode/svg/chat_history.svg +0 -0
- {open_swarm-0.1.1743416034 → open_swarm-0.1.1743449197}/src/swarm/static/rest_mode/svg/close.svg +0 -0
- {open_swarm-0.1.1743416034 → open_swarm-0.1.1743449197}/src/swarm/static/rest_mode/svg/copy.svg +0 -0
- {open_swarm-0.1.1743416034 → open_swarm-0.1.1743449197}/src/swarm/static/rest_mode/svg/dark_mode.svg +0 -0
- {open_swarm-0.1.1743416034 → open_swarm-0.1.1743449197}/src/swarm/static/rest_mode/svg/edit.svg +0 -0
- {open_swarm-0.1.1743416034 → open_swarm-0.1.1743449197}/src/swarm/static/rest_mode/svg/layout.svg +0 -0
- {open_swarm-0.1.1743416034 → open_swarm-0.1.1743449197}/src/swarm/static/rest_mode/svg/logo.svg +0 -0
- {open_swarm-0.1.1743416034 → open_swarm-0.1.1743449197}/src/swarm/static/rest_mode/svg/logout.svg +0 -0
- {open_swarm-0.1.1743416034 → open_swarm-0.1.1743449197}/src/swarm/static/rest_mode/svg/mobile.svg +0 -0
- {open_swarm-0.1.1743416034 → open_swarm-0.1.1743449197}/src/swarm/static/rest_mode/svg/new_chat.svg +0 -0
- {open_swarm-0.1.1743416034 → open_swarm-0.1.1743449197}/src/swarm/static/rest_mode/svg/not_visible.svg +0 -0
- {open_swarm-0.1.1743416034 → open_swarm-0.1.1743449197}/src/swarm/static/rest_mode/svg/plus.svg +0 -0
- {open_swarm-0.1.1743416034 → open_swarm-0.1.1743449197}/src/swarm/static/rest_mode/svg/run_code.svg +0 -0
- {open_swarm-0.1.1743416034 → open_swarm-0.1.1743449197}/src/swarm/static/rest_mode/svg/save.svg +0 -0
- {open_swarm-0.1.1743416034 → open_swarm-0.1.1743449197}/src/swarm/static/rest_mode/svg/search.svg +0 -0
- {open_swarm-0.1.1743416034 → open_swarm-0.1.1743449197}/src/swarm/static/rest_mode/svg/settings.svg +0 -0
- {open_swarm-0.1.1743416034 → open_swarm-0.1.1743449197}/src/swarm/static/rest_mode/svg/speaker.svg +0 -0
- {open_swarm-0.1.1743416034 → open_swarm-0.1.1743449197}/src/swarm/static/rest_mode/svg/stop.svg +0 -0
- {open_swarm-0.1.1743416034 → open_swarm-0.1.1743449197}/src/swarm/static/rest_mode/svg/thumbs_down.svg +0 -0
- {open_swarm-0.1.1743416034 → open_swarm-0.1.1743449197}/src/swarm/static/rest_mode/svg/thumbs_up.svg +0 -0
- {open_swarm-0.1.1743416034 → open_swarm-0.1.1743449197}/src/swarm/static/rest_mode/svg/toggle_off.svg +0 -0
- {open_swarm-0.1.1743416034 → open_swarm-0.1.1743449197}/src/swarm/static/rest_mode/svg/toggle_on.svg +0 -0
- {open_swarm-0.1.1743416034 → open_swarm-0.1.1743449197}/src/swarm/static/rest_mode/svg/trash.svg +0 -0
- {open_swarm-0.1.1743416034 → open_swarm-0.1.1743449197}/src/swarm/static/rest_mode/svg/undo.svg +0 -0
- {open_swarm-0.1.1743416034 → open_swarm-0.1.1743449197}/src/swarm/static/rest_mode/svg/visible.svg +0 -0
- {open_swarm-0.1.1743416034 → open_swarm-0.1.1743449197}/src/swarm/static/rest_mode/svg/voice.svg +0 -0
- {open_swarm-0.1.1743416034 → open_swarm-0.1.1743449197}/src/swarm/templates/account/login.html +0 -0
- {open_swarm-0.1.1743416034 → open_swarm-0.1.1743449197}/src/swarm/templates/account/signup.html +0 -0
- {open_swarm-0.1.1743416034 → open_swarm-0.1.1743449197}/src/swarm/templates/base.html +0 -0
- {open_swarm-0.1.1743416034 → open_swarm-0.1.1743449197}/src/swarm/templates/chat.html +0 -0
- {open_swarm-0.1.1743416034 → open_swarm-0.1.1743449197}/src/swarm/templates/index.html +0 -0
- {open_swarm-0.1.1743416034 → open_swarm-0.1.1743449197}/src/swarm/templates/rest_mode/components/chat_sidebar.html +0 -0
- {open_swarm-0.1.1743416034 → open_swarm-0.1.1743449197}/src/swarm/templates/rest_mode/components/header.html +0 -0
- {open_swarm-0.1.1743416034 → open_swarm-0.1.1743449197}/src/swarm/templates/rest_mode/components/main_chat_pane.html +0 -0
- {open_swarm-0.1.1743416034 → open_swarm-0.1.1743449197}/src/swarm/templates/rest_mode/components/settings_dialog.html +0 -0
- {open_swarm-0.1.1743416034 → open_swarm-0.1.1743449197}/src/swarm/templates/rest_mode/components/splash_screen.html +0 -0
- {open_swarm-0.1.1743416034 → open_swarm-0.1.1743449197}/src/swarm/templates/rest_mode/components/top_bar.html +0 -0
- {open_swarm-0.1.1743416034 → open_swarm-0.1.1743449197}/src/swarm/templates/rest_mode/message_ui.html +0 -0
- {open_swarm-0.1.1743416034 → open_swarm-0.1.1743449197}/src/swarm/templates/rest_mode/slackbot.html +0 -0
- {open_swarm-0.1.1743416034 → open_swarm-0.1.1743449197}/src/swarm/templates/simple_blueprint_page.html +0 -0
- {open_swarm-0.1.1743416034 → open_swarm-0.1.1743449197}/src/swarm/templates/websocket_partials/final_system_message.html +0 -0
- {open_swarm-0.1.1743416034 → open_swarm-0.1.1743449197}/src/swarm/templates/websocket_partials/system_message.html +0 -0
- {open_swarm-0.1.1743416034 → open_swarm-0.1.1743449197}/src/swarm/templates/websocket_partials/user_message.html +0 -0
- {open_swarm-0.1.1743416034 → open_swarm-0.1.1743449197}/src/swarm/tool_executor.py +0 -0
- {open_swarm-0.1.1743416034 → open_swarm-0.1.1743449197}/src/swarm/urls.py +0 -0
- {open_swarm-0.1.1743416034 → open_swarm-0.1.1743449197}/src/swarm/util.py +0 -0
- {open_swarm-0.1.1743416034 → open_swarm-0.1.1743449197}/src/swarm/utils/color_utils.py +0 -0
- {open_swarm-0.1.1743416034 → open_swarm-0.1.1743449197}/src/swarm/utils/context_utils.py +0 -0
- {open_swarm-0.1.1743416034 → open_swarm-0.1.1743449197}/src/swarm/utils/general_utils.py +0 -0
- {open_swarm-0.1.1743416034 → open_swarm-0.1.1743449197}/src/swarm/utils/log_utils.py +0 -0
- {open_swarm-0.1.1743416034 → open_swarm-0.1.1743449197}/src/swarm/utils/logger.py +0 -0
- {open_swarm-0.1.1743416034 → open_swarm-0.1.1743449197}/src/swarm/utils/logger_setup.py +0 -0
- {open_swarm-0.1.1743416034 → open_swarm-0.1.1743449197}/src/swarm/utils/message_sequence.py +0 -0
- {open_swarm-0.1.1743416034 → open_swarm-0.1.1743449197}/src/swarm/utils/message_utils.py +0 -0
- {open_swarm-0.1.1743416034 → open_swarm-0.1.1743449197}/src/swarm/utils/redact.py +0 -0
- {open_swarm-0.1.1743416034 → open_swarm-0.1.1743449197}/src/swarm/views/__init__.py +0 -0
- {open_swarm-0.1.1743416034 → open_swarm-0.1.1743449197}/src/swarm/views/api_views.py +0 -0
- {open_swarm-0.1.1743416034 → open_swarm-0.1.1743449197}/src/swarm/views/chat_views.py +0 -0
- {open_swarm-0.1.1743416034 → open_swarm-0.1.1743449197}/src/swarm/views/core_views.py +0 -0
- {open_swarm-0.1.1743416034 → open_swarm-0.1.1743449197}/src/swarm/views/message_views.py +0 -0
- {open_swarm-0.1.1743416034 → open_swarm-0.1.1743449197}/src/swarm/views/model_views.py +0 -0
- {open_swarm-0.1.1743416034 → open_swarm-0.1.1743449197}/src/swarm/views/utils.py +0 -0
- {open_swarm-0.1.1743416034 → open_swarm-0.1.1743449197}/src/swarm/views/web_views.py +0 -0
- {open_swarm-0.1.1743416034 → open_swarm-0.1.1743449197}/src/swarm/wsgi.py +0 -0
- {open_swarm-0.1.1743416034 → open_swarm-0.1.1743449197}/tests/__init__.py +0 -0
- {open_swarm-0.1.1743416034 → open_swarm-0.1.1743449197}/tests/api/conftest.py +0 -0
- {open_swarm-0.1.1743416034 → open_swarm-0.1.1743449197}/tests/api/test_chat_completions_auth_async.py +0 -0
- {open_swarm-0.1.1743416034 → open_swarm-0.1.1743449197}/tests/api/test_chat_completions_failing_async.py +0 -0
- {open_swarm-0.1.1743416034 → open_swarm-0.1.1743449197}/tests/api/test_chat_completions_validation_async.py +0 -0
- {open_swarm-0.1.1743416034 → open_swarm-0.1.1743449197}/tests/blueprints/test_chatbot.py +0 -0
- {open_swarm-0.1.1743416034 → open_swarm-0.1.1743449197}/tests/blueprints/test_digitalbutlers.py +0 -0
- {open_swarm-0.1.1743416034 → open_swarm-0.1.1743449197}/tests/blueprints/test_dilbot_universe.py +0 -0
- {open_swarm-0.1.1743416034 → open_swarm-0.1.1743449197}/tests/blueprints/test_divine_code.py +0 -0
- {open_swarm-0.1.1743416034 → open_swarm-0.1.1743449197}/tests/blueprints/test_echocraft.py +0 -0
- {open_swarm-0.1.1743416034 → open_swarm-0.1.1743449197}/tests/blueprints/test_family_ties.py +0 -0
- {open_swarm-0.1.1743416034 → open_swarm-0.1.1743449197}/tests/blueprints/test_gaggle.py +0 -0
- {open_swarm-0.1.1743416034 → open_swarm-0.1.1743449197}/tests/blueprints/test_gotchaman.py +0 -0
- {open_swarm-0.1.1743416034 → open_swarm-0.1.1743449197}/tests/blueprints/test_mcp_demo.py +0 -0
- {open_swarm-0.1.1743416034 → open_swarm-0.1.1743449197}/tests/blueprints/test_mission_improbable.py +0 -0
- {open_swarm-0.1.1743416034 → open_swarm-0.1.1743449197}/tests/blueprints/test_monkai_magic.py +0 -0
- {open_swarm-0.1.1743416034 → open_swarm-0.1.1743449197}/tests/blueprints/test_nebula_shellz.py +0 -0
- {open_swarm-0.1.1743416034 → open_swarm-0.1.1743449197}/tests/blueprints/test_omniplex.py +0 -0
- {open_swarm-0.1.1743416034 → open_swarm-0.1.1743449197}/tests/blueprints/test_suggestion.py +0 -0
- {open_swarm-0.1.1743416034 → open_swarm-0.1.1743449197}/tests/blueprints/test_unapologetic_press.py +0 -0
- {open_swarm-0.1.1743416034 → open_swarm-0.1.1743449197}/tests/blueprints/test_whiskeytangofoxtrot.py +0 -0
- {open_swarm-0.1.1743416034 → open_swarm-0.1.1743449197}/tests/cli/test_launchers.py +0 -0
- {open_swarm-0.1.1743416034 → open_swarm-0.1.1743449197}/tests/cli/test_list_blueprints.py +0 -0
- {open_swarm-0.1.1743416034 → open_swarm-0.1.1743449197}/tests/conftest.py +0 -0
- {open_swarm-0.1.1743416034 → open_swarm-0.1.1743449197}/tests/swarm_config.json +0 -0
- {open_swarm-0.1.1743416034 → open_swarm-0.1.1743449197}/tests/system/test_burnt_noodles.sh +0 -0
- {open_swarm-0.1.1743416034 → open_swarm-0.1.1743449197}/tests/system/test_chucks_angels.sh +0 -0
- {open_swarm-0.1.1743416034 → open_swarm-0.1.1743449197}/tests/system/test_digitalbutlers.sh +0 -0
- {open_swarm-0.1.1743416034 → open_swarm-0.1.1743449197}/tests/system/test_dilbot_universe.sh +0 -0
- {open_swarm-0.1.1743416034 → open_swarm-0.1.1743449197}/tests/system/test_divine_code.sh +0 -0
- {open_swarm-0.1.1743416034 → open_swarm-0.1.1743449197}/tests/system/test_django_chat.sh +0 -0
- {open_swarm-0.1.1743416034 → open_swarm-0.1.1743449197}/tests/system/test_echocraft.sh +0 -0
- {open_swarm-0.1.1743416034 → open_swarm-0.1.1743449197}/tests/system/test_family_ties.sh +0 -0
- {open_swarm-0.1.1743416034 → open_swarm-0.1.1743449197}/tests/system/test_flock.sh +0 -0
- {open_swarm-0.1.1743416034 → open_swarm-0.1.1743449197}/tests/system/test_gaggle.sh +0 -0
- {open_swarm-0.1.1743416034 → open_swarm-0.1.1743449197}/tests/system/test_gotchaman.sh +0 -0
- {open_swarm-0.1.1743416034 → open_swarm-0.1.1743449197}/tests/system/test_monkai-magic.sh +0 -0
- {open_swarm-0.1.1743416034 → open_swarm-0.1.1743449197}/tests/system/test_nebula_shellz.sh +0 -0
- {open_swarm-0.1.1743416034 → open_swarm-0.1.1743449197}/tests/system/test_omniplex.sh +0 -0
- {open_swarm-0.1.1743416034 → open_swarm-0.1.1743449197}/tests/system/test_rue-code.sh +0 -0
- {open_swarm-0.1.1743416034 → open_swarm-0.1.1743449197}/tests/system/test_suggestion.sh +0 -0
- {open_swarm-0.1.1743416034 → open_swarm-0.1.1743449197}/tests/system/test_unapologetic_press.sh +0 -0
- {open_swarm-0.1.1743416034 → open_swarm-0.1.1743449197}/tests/system/test_university.sh +0 -0
- {open_swarm-0.1.1743416034 → open_swarm-0.1.1743449197}/tests/system/test_whiskeytango_foxtrot.sh +0 -0
- {open_swarm-0.1.1743416034 → open_swarm-0.1.1743449197}/tests/test_blueprint_loading.py +0 -0
- {open_swarm-0.1.1743416034 → open_swarm-0.1.1743449197}/tests/test_cli_mode_selection.py +0 -0
- {open_swarm-0.1.1743416034 → open_swarm-0.1.1743449197}/tests/test_core_filter_duplicate_system_messages.py +0 -0
- {open_swarm-0.1.1743416034 → open_swarm-0.1.1743449197}/tests/test_core_filter_messages.py +0 -0
- {open_swarm-0.1.1743416034 → open_swarm-0.1.1743449197}/tests/test_core_truncate_message_history.py +0 -0
- {open_swarm-0.1.1743416034 → open_swarm-0.1.1743449197}/tests/test_core_update_null_content.py +0 -0
- {open_swarm-0.1.1743416034 → open_swarm-0.1.1743449197}/tests/test_dummy.py +0 -0
- {open_swarm-0.1.1743416034 → open_swarm-0.1.1743449197}/tests/test_truncate_message_history.py +0 -0
- {open_swarm-0.1.1743416034 → open_swarm-0.1.1743449197}/tests/unit/blueprints/rue_code/test_rue_code_tools.py +0 -0
- {open_swarm-0.1.1743416034 → open_swarm-0.1.1743449197}/tests/unit/test_blueprint_base_config.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.1743449197
|
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,304 @@
|
|
1
|
+
import logging
|
2
|
+
import os
|
3
|
+
import sys
|
4
|
+
import asyncio
|
5
|
+
import subprocess
|
6
|
+
import shlex # Added for safe command splitting
|
7
|
+
import re
|
8
|
+
import inspect
|
9
|
+
from pathlib import Path # Use pathlib for better path handling
|
10
|
+
from typing import Dict, Any, List, Optional, ClassVar, AsyncGenerator
|
11
|
+
|
12
|
+
try:
|
13
|
+
# Core imports from openai-agents
|
14
|
+
from agents import Agent, Tool, function_tool, Runner
|
15
|
+
from agents.mcp import MCPServer
|
16
|
+
from agents.models.interface import Model
|
17
|
+
from agents.models.openai_chatcompletions import OpenAIChatCompletionsModel
|
18
|
+
from openai import AsyncOpenAI
|
19
|
+
|
20
|
+
# Import our custom base class
|
21
|
+
from swarm.extensions.blueprint.blueprint_base import BlueprintBase
|
22
|
+
except ImportError as e:
|
23
|
+
# Provide more helpful error message
|
24
|
+
print(f"ERROR: Import failed in BurntNoodlesBlueprint: {e}. Check 'openai-agents' install and project structure.")
|
25
|
+
print(f"Attempted import from directory: {os.path.dirname(__file__)}")
|
26
|
+
print(f"sys.path: {sys.path}")
|
27
|
+
sys.exit(1)
|
28
|
+
|
29
|
+
# Configure logging for this blueprint module
|
30
|
+
logger = logging.getLogger(__name__)
|
31
|
+
# Logging level is controlled by BlueprintBase based on --debug flag
|
32
|
+
|
33
|
+
# --- Tool Logic Definitions (Undecorated) ---
|
34
|
+
def _git_status_logic() -> str:
|
35
|
+
"""Executes 'git status --porcelain' and returns the current repository status."""
|
36
|
+
logger.info("Executing git status --porcelain")
|
37
|
+
try:
|
38
|
+
result = subprocess.run(["git", "status", "--porcelain"], capture_output=True, text=True, check=True, timeout=30)
|
39
|
+
output = result.stdout.strip()
|
40
|
+
logger.debug(f"Git status raw output:\n{output}")
|
41
|
+
return f"OK: Git Status:\n{output}" if output else "OK: No changes detected in the working directory."
|
42
|
+
except FileNotFoundError: logger.error("Git command not found."); return "Error: git command not found."
|
43
|
+
except subprocess.CalledProcessError as e: logger.error(f"Error executing git status: {e.stderr}"); return f"Error executing git status: {e.stderr}"
|
44
|
+
except subprocess.TimeoutExpired: logger.error("Git status command timed out."); return "Error: Git status command timed out."
|
45
|
+
except Exception as e: logger.error(f"Unexpected error during git status: {e}", exc_info=logger.level <= logging.DEBUG); return f"Error during git status: {e}"
|
46
|
+
|
47
|
+
def _git_diff_logic() -> str:
|
48
|
+
"""Executes 'git diff' and returns the differences in the working directory."""
|
49
|
+
logger.info("Executing git diff")
|
50
|
+
try:
|
51
|
+
result = subprocess.run(["git", "diff"], capture_output=True, text=True, check=False, timeout=30)
|
52
|
+
output = result.stdout; stderr = result.stderr.strip()
|
53
|
+
if result.returncode != 0 and stderr: logger.error(f"Error executing git diff (Exit Code {result.returncode}): {stderr}"); return f"Error executing git diff: {stderr}"
|
54
|
+
logger.debug(f"Git diff raw output (Exit Code {result.returncode}):\n{output[:1000]}...")
|
55
|
+
return f"OK: Git Diff Output:\n{output}" if output else "OK: No differences found."
|
56
|
+
except FileNotFoundError: logger.error("Git command not found."); return "Error: git command not found."
|
57
|
+
except subprocess.TimeoutExpired: logger.error("Git diff command timed out."); return "Error: Git diff command timed out."
|
58
|
+
except Exception as e: logger.error(f"Unexpected error during git diff: {e}", exc_info=logger.level <= logging.DEBUG); return f"Error during git diff: {e}"
|
59
|
+
|
60
|
+
def _git_add_logic(file_path: str = ".") -> str:
|
61
|
+
"""Executes 'git add' to stage changes for the specified file or all changes (default '.')."""
|
62
|
+
logger.info(f"Executing git add {file_path}")
|
63
|
+
try:
|
64
|
+
result = subprocess.run(["git", "add", file_path], capture_output=True, text=True, check=True, timeout=30)
|
65
|
+
logger.debug(f"Git add '{file_path}' completed successfully.")
|
66
|
+
return f"OK: Staged '{file_path}' successfully."
|
67
|
+
except FileNotFoundError: logger.error("Git command not found."); return "Error: git command not found."
|
68
|
+
except subprocess.CalledProcessError as e: logger.error(f"Error executing git add '{file_path}': {e.stderr}"); return f"Error executing git add '{file_path}': {e.stderr}"
|
69
|
+
except subprocess.TimeoutExpired: logger.error(f"Git add command timed out for '{file_path}'."); return f"Error: Git add command timed out for '{file_path}'."
|
70
|
+
except Exception as e: logger.error(f"Unexpected error during git add '{file_path}': {e}", exc_info=logger.level <= logging.DEBUG); return f"Error during git add '{file_path}': {e}"
|
71
|
+
|
72
|
+
def _git_commit_logic(message: str) -> str:
|
73
|
+
"""Executes 'git commit' with a provided commit message."""
|
74
|
+
logger.info(f"Executing git commit -m '{message[:50]}...'")
|
75
|
+
if not message or not message.strip(): logger.warning("Git commit attempted with empty message."); return "Error: Commit message cannot be empty."
|
76
|
+
try:
|
77
|
+
result = subprocess.run(["git", "commit", "-m", message], capture_output=True, text=True, check=False, timeout=30)
|
78
|
+
output = result.stdout.strip(); stderr = result.stderr.strip()
|
79
|
+
logger.debug(f"Git commit raw output (Exit Code {result.returncode}):\nSTDOUT: {output}\nSTDERR: {stderr}")
|
80
|
+
if "nothing to commit" in output or "nothing added to commit" in output or "no changes added to commit" in output:
|
81
|
+
logger.info("Git commit reported: Nothing to commit."); return "OK: Nothing to commit."
|
82
|
+
if result.returncode == 0: return f"OK: Committed with message '{message}'.\n{output}"
|
83
|
+
else: error_detail = stderr if stderr else output; logger.error(f"Error executing git commit (Exit Code {result.returncode}): {error_detail}"); return f"Error executing git commit: {error_detail}"
|
84
|
+
except FileNotFoundError: logger.error("Git command not found."); return "Error: git command not found."
|
85
|
+
except subprocess.TimeoutExpired: logger.error("Git commit command timed out."); return "Error: Git commit command timed out."
|
86
|
+
except Exception as e: logger.error(f"Unexpected error during git commit: {e}", exc_info=logger.level <= logging.DEBUG); return f"Error during git commit: {e}"
|
87
|
+
|
88
|
+
def _git_push_logic() -> str:
|
89
|
+
"""Executes 'git push' to push staged commits to the remote repository."""
|
90
|
+
logger.info("Executing git push")
|
91
|
+
try:
|
92
|
+
result = subprocess.run(["git", "push"], capture_output=True, text=True, check=True, timeout=120)
|
93
|
+
output = result.stdout.strip() + "\n" + result.stderr.strip()
|
94
|
+
logger.debug(f"Git push raw output:\n{output}")
|
95
|
+
return f"OK: Push completed.\n{output.strip()}"
|
96
|
+
except FileNotFoundError: logger.error("Git command not found."); return "Error: git command not found."
|
97
|
+
except subprocess.CalledProcessError as e: error_output = e.stdout.strip() + "\n" + e.stderr.strip(); logger.error(f"Error executing git push: {error_output}"); return f"Error executing git push: {error_output.strip()}"
|
98
|
+
except subprocess.TimeoutExpired: logger.error("Git push command timed out."); return "Error: Git push command timed out."
|
99
|
+
except Exception as e: logger.error(f"Unexpected error during git push: {e}", exc_info=logger.level <= logging.DEBUG); return f"Error during git push: {e}"
|
100
|
+
|
101
|
+
def _run_npm_test_logic(args: str = "") -> str:
|
102
|
+
"""Executes 'npm run test' with optional arguments."""
|
103
|
+
try:
|
104
|
+
cmd_list = ["npm", "run", "test"] + (shlex.split(args) if args else []); cmd_str = ' '.join(cmd_list)
|
105
|
+
logger.info(f"Executing npm test: {cmd_str}")
|
106
|
+
result = subprocess.run(cmd_list, capture_output=True, text=True, check=False, timeout=120)
|
107
|
+
output = f"Exit Code: {result.returncode}\nSTDOUT:\n{result.stdout.strip()}\nSTDERR:\n{result.stderr.strip()}"
|
108
|
+
if result.returncode == 0: logger.debug(f"npm test completed successfully:\n{output}"); return f"OK: npm test finished.\n{output}"
|
109
|
+
else: logger.error(f"npm test failed (Exit Code {result.returncode}):\n{output}"); return f"Error: npm test failed.\n{output}"
|
110
|
+
except FileNotFoundError: logger.error("npm command not found."); return "Error: npm command not found."
|
111
|
+
except subprocess.TimeoutExpired: logger.error("npm test command timed out."); return "Error: npm test command timed out."
|
112
|
+
except Exception as e: logger.error(f"Unexpected error during npm test: {e}", exc_info=logger.level <= logging.DEBUG); return f"Error during npm test: {e}"
|
113
|
+
|
114
|
+
def _run_pytest_logic(args: str = "") -> str:
|
115
|
+
"""Executes 'uv run pytest' with optional arguments."""
|
116
|
+
try:
|
117
|
+
cmd_list = ["uv", "run", "pytest"] + (shlex.split(args) if args else []); cmd_str = ' '.join(cmd_list)
|
118
|
+
logger.info(f"Executing pytest via uv: {cmd_str}")
|
119
|
+
result = subprocess.run(cmd_list, capture_output=True, text=True, check=False, timeout=120)
|
120
|
+
output = f"Exit Code: {result.returncode}\nSTDOUT:\n{result.stdout.strip()}\nSTDERR:\n{result.stderr.strip()}"
|
121
|
+
if result.returncode == 0: logger.debug(f"pytest completed successfully:\n{output}"); return f"OK: pytest finished successfully.\n{output}"
|
122
|
+
else: logger.warning(f"pytest finished with failures (Exit Code {result.returncode}):\n{output}"); return f"OK: Pytest finished with failures (Exit Code {result.returncode}).\n{output}"
|
123
|
+
except FileNotFoundError: logger.error("uv command not found."); return "Error: uv command not found."
|
124
|
+
except subprocess.TimeoutExpired: logger.error("pytest command timed out."); return "Error: pytest command timed out."
|
125
|
+
except Exception as e: logger.error(f"Unexpected error during pytest: {e}", exc_info=logger.level <= logging.DEBUG); return f"Error during pytest: {e}"
|
126
|
+
|
127
|
+
# --- Tool Definitions (Decorated - reverted to default naming) ---
|
128
|
+
git_status = function_tool(_git_status_logic)
|
129
|
+
git_diff = function_tool(_git_diff_logic)
|
130
|
+
git_add = function_tool(_git_add_logic)
|
131
|
+
git_commit = function_tool(_git_commit_logic)
|
132
|
+
git_push = function_tool(_git_push_logic)
|
133
|
+
run_npm_test = function_tool(_run_npm_test_logic)
|
134
|
+
run_pytest = function_tool(_run_pytest_logic)
|
135
|
+
|
136
|
+
# --- Agent Instructions ---
|
137
|
+
# (Instructions remain the same)
|
138
|
+
michael_instructions = """
|
139
|
+
You are Michael Toasted, the resolute leader of the Burnt Noodles creative team.
|
140
|
+
Your primary role is to understand the user's request, break it down into actionable steps,
|
141
|
+
and delegate tasks appropriately to your team members: Fiona Flame (Git operations) and Sam Ashes (Testing).
|
142
|
+
You should only execute simple Git status checks (`git_status`, `git_diff`) yourself. Delegate all other Git actions (add, commit, push) to Fiona. Delegate all testing actions (npm test, pytest) to Sam.
|
143
|
+
Synthesize the results from your team and provide the final response to the user.
|
144
|
+
Available Function Tools (for you): git_status, git_diff.
|
145
|
+
Available Agent Tools (for delegation): Fiona_Flame, Sam_Ashes.
|
146
|
+
"""
|
147
|
+
fiona_instructions = """
|
148
|
+
You are Fiona Flame, the git specialist. Execute git commands precisely as requested using your available function tools:
|
149
|
+
`git_status`, `git_diff`, `git_add`, `git_commit`, `git_push`.
|
150
|
+
When asked to commit, analyze the diff if necessary and generate concise, informative conventional commit messages (e.g., 'feat: ...', 'fix: ...', 'refactor: ...', 'chore: ...').
|
151
|
+
Always stage changes using `git_add` before committing.
|
152
|
+
If asked to push, first ask the user (Michael) for confirmation before executing `git_push`.
|
153
|
+
If a task involves testing (like running tests after a commit), delegate it to the Sam_Ashes agent tool.
|
154
|
+
For tasks outside your Git domain, report back to Michael; do not use the Michael_Toasted tool directly.
|
155
|
+
Available Function Tools: git_status, git_diff, git_add, git_commit, git_push.
|
156
|
+
Available Agent Tools: Sam_Ashes.
|
157
|
+
"""
|
158
|
+
sam_instructions = """
|
159
|
+
You are Sam Ashes, the meticulous testing operative. Execute test commands using your available function tools: `run_npm_test` or `run_pytest`.
|
160
|
+
Interpret the results: Report failures immediately and clearly. If tests pass, consider running with coverage (e.g., using `uv run pytest --cov` via the `run_pytest` tool) if appropriate or requested, and report the coverage summary.
|
161
|
+
For tasks outside testing (e.g., needing code changes before testing, or git operations), refer back to Michael; do not use the Michael_Toasted or Fiona_Flame tools directly.
|
162
|
+
Available Function Tools: run_npm_test, run_pytest.
|
163
|
+
Available Agent Tools: None (Report back to Michael for delegation).
|
164
|
+
"""
|
165
|
+
|
166
|
+
# --- Blueprint Definition ---
|
167
|
+
class BurntNoodlesBlueprint(BlueprintBase):
|
168
|
+
metadata: ClassVar[Dict[str, Any]] = {
|
169
|
+
"name": "BurntNoodlesBlueprint",
|
170
|
+
"title": "Burnt Noodles",
|
171
|
+
"description": "A multi-agent team managing Git operations and code testing.",
|
172
|
+
"version": "1.1.0",
|
173
|
+
"author": "Open Swarm Team (Refactored)",
|
174
|
+
"tags": ["git", "test", "multi-agent", "collaboration", "refactor"],
|
175
|
+
"required_mcp_servers": [],
|
176
|
+
}
|
177
|
+
|
178
|
+
_openai_client_cache: Dict[str, AsyncOpenAI] = {}
|
179
|
+
_model_instance_cache: Dict[str, Model] = {}
|
180
|
+
|
181
|
+
def _get_model_instance(self, profile_name: str) -> Model:
|
182
|
+
if profile_name in self._model_instance_cache:
|
183
|
+
logger.debug(f"Using cached Model instance for profile '{profile_name}'.")
|
184
|
+
return self._model_instance_cache[profile_name]
|
185
|
+
|
186
|
+
logger.debug(f"Creating new Model instance for profile '{profile_name}'.")
|
187
|
+
profile_data = getattr(self, "get_llm_profile", lambda prof: {"provider": "openai", "model": "gpt-mock"})(profile_name)
|
188
|
+
if not profile_data:
|
189
|
+
logger.critical(f"Cannot create Model instance: LLM profile '{profile_name}' (or 'default') not found in configuration.")
|
190
|
+
raise ValueError(f"Missing LLM profile configuration for '{profile_name}' or 'default'.")
|
191
|
+
|
192
|
+
provider = profile_data.get("provider", "openai").lower()
|
193
|
+
model_name = profile_data.get("model")
|
194
|
+
if not model_name:
|
195
|
+
logger.critical(f"LLM profile '{profile_name}' is missing the required 'model' key.")
|
196
|
+
raise ValueError(f"Missing 'model' key in LLM profile '{profile_name}'.")
|
197
|
+
|
198
|
+
if provider != "openai":
|
199
|
+
logger.error(f"Unsupported LLM provider '{provider}' in profile '{profile_name}'. Only 'openai' is supported in this blueprint.")
|
200
|
+
raise ValueError(f"Unsupported LLM provider: {provider}")
|
201
|
+
|
202
|
+
client_cache_key = f"{provider}_{profile_data.get('base_url')}"
|
203
|
+
if client_cache_key not in self._openai_client_cache:
|
204
|
+
client_kwargs = { "api_key": profile_data.get("api_key"), "base_url": profile_data.get("base_url") }
|
205
|
+
filtered_client_kwargs = {k: v for k, v in client_kwargs.items() if v is not None}
|
206
|
+
log_client_kwargs = {k:v for k,v in filtered_client_kwargs.items() if k != 'api_key'}
|
207
|
+
logger.debug(f"Creating new AsyncOpenAI client for profile '{profile_name}' with config: {log_client_kwargs}")
|
208
|
+
try:
|
209
|
+
self._openai_client_cache[client_cache_key] = AsyncOpenAI(**filtered_client_kwargs)
|
210
|
+
except Exception as e:
|
211
|
+
logger.error(f"Failed to create AsyncOpenAI client for profile '{profile_name}': {e}", exc_info=True)
|
212
|
+
raise ValueError(f"Failed to initialize OpenAI client for profile '{profile_name}': {e}") from e
|
213
|
+
|
214
|
+
openai_client_instance = self._openai_client_cache[client_cache_key]
|
215
|
+
|
216
|
+
logger.debug(f"Instantiating OpenAIChatCompletionsModel(model='{model_name}') with client instance for profile '{profile_name}'.")
|
217
|
+
try:
|
218
|
+
model_instance = OpenAIChatCompletionsModel(model=model_name, openai_client=openai_client_instance)
|
219
|
+
self._model_instance_cache[profile_name] = model_instance
|
220
|
+
return model_instance
|
221
|
+
except Exception as e:
|
222
|
+
logger.error(f"Failed to instantiate OpenAIChatCompletionsModel for profile '{profile_name}': {e}", exc_info=True)
|
223
|
+
raise ValueError(f"Failed to initialize LLM provider for profile '{profile_name}': {e}") from e
|
224
|
+
|
225
|
+
def create_starting_agent(self, mcp_servers: List[MCPServer]) -> Agent:
|
226
|
+
logger.debug("Creating Burnt Noodles agent team...")
|
227
|
+
config = self._load_configuration() if getattr(self, "config", None) is None else self.config
|
228
|
+
self._model_instance_cache = {}
|
229
|
+
self._openai_client_cache = {}
|
230
|
+
|
231
|
+
default_profile_name = config.get("llm_profile", "default")
|
232
|
+
logger.debug(f"Using LLM profile '{default_profile_name}' for all Burnt Noodles agents.")
|
233
|
+
default_model_instance = self._get_model_instance(default_profile_name)
|
234
|
+
|
235
|
+
# --- Use the decorated tool variables ---
|
236
|
+
fiona_flame = Agent(
|
237
|
+
name="Fiona_Flame",
|
238
|
+
model=default_model_instance,
|
239
|
+
instructions=fiona_instructions,
|
240
|
+
tools=[git_status, git_diff, git_add, git_commit, git_push] # Agent tools added later
|
241
|
+
)
|
242
|
+
sam_ashes = Agent(
|
243
|
+
name="Sam_Ashes",
|
244
|
+
model=default_model_instance,
|
245
|
+
instructions=sam_instructions,
|
246
|
+
tools=[run_npm_test, run_pytest] # Agent tools added later
|
247
|
+
)
|
248
|
+
michael_toasted = Agent(
|
249
|
+
name="Michael_Toasted",
|
250
|
+
model=default_model_instance,
|
251
|
+
instructions=michael_instructions,
|
252
|
+
tools=[
|
253
|
+
git_status, # Michael's direct tools
|
254
|
+
git_diff,
|
255
|
+
fiona_flame.as_tool(
|
256
|
+
tool_name="Fiona_Flame",
|
257
|
+
tool_description="Delegate Git operations (add, commit, push) or complex status/diff queries to Fiona."
|
258
|
+
),
|
259
|
+
sam_ashes.as_tool(
|
260
|
+
tool_name="Sam_Ashes",
|
261
|
+
tool_description="Delegate testing tasks (npm test, pytest) to Sam."
|
262
|
+
),
|
263
|
+
],
|
264
|
+
mcp_servers=mcp_servers
|
265
|
+
)
|
266
|
+
# --- End tool variable usage ---
|
267
|
+
|
268
|
+
fiona_flame.tools.append(
|
269
|
+
sam_ashes.as_tool(tool_name="Sam_Ashes", tool_description="Delegate testing tasks (npm test, pytest) to Sam.")
|
270
|
+
)
|
271
|
+
|
272
|
+
logger.debug("Burnt Noodles agent team created successfully. Michael Toasted is the starting agent.")
|
273
|
+
return michael_toasted
|
274
|
+
|
275
|
+
async def run(self, messages: List[Dict[str, Any]], **kwargs) -> AsyncGenerator[Dict[str, Any], None]:
|
276
|
+
"""
|
277
|
+
Main execution entry point for the Burnt Noodles blueprint.
|
278
|
+
Delegates to _run_non_interactive for CLI-like execution.
|
279
|
+
"""
|
280
|
+
logger.info("BurntNoodlesBlueprint run method called.")
|
281
|
+
instruction = messages[-1].get("content", "") if messages else ""
|
282
|
+
async for chunk in self._run_non_interactive(instruction, **kwargs):
|
283
|
+
yield chunk
|
284
|
+
logger.info("BurntNoodlesBlueprint run method finished.")
|
285
|
+
|
286
|
+
async def _run_non_interactive(self, instruction: str, **kwargs) -> AsyncGenerator[Dict[str, Any], None]:
|
287
|
+
"""Helper to run the agent flow based on an instruction."""
|
288
|
+
logger.info(f"Running Burnt Noodles non-interactively with instruction: '{instruction[:100]}...'")
|
289
|
+
mcp_servers = kwargs.get("mcp_servers", [])
|
290
|
+
starting_agent = self.create_starting_agent(mcp_servers=mcp_servers)
|
291
|
+
runner = Runner(agent=starting_agent)
|
292
|
+
try:
|
293
|
+
final_result = await runner.run(instruction)
|
294
|
+
logger.info(f"Non-interactive run finished. Final Output: {final_result.final_output}")
|
295
|
+
yield { "messages": [ {"role": "assistant", "content": final_result.final_output} ] }
|
296
|
+
except Exception as e:
|
297
|
+
logger.error(f"Error during non-interactive run: {e}", exc_info=True)
|
298
|
+
yield { "messages": [ {"role": "assistant", "content": f"An error occurred: {e}"} ] }
|
299
|
+
|
300
|
+
|
301
|
+
# Standard Python entry point for direct script execution
|
302
|
+
if __name__ == "__main__":
|
303
|
+
BurntNoodlesBlueprint.main()
|
304
|
+
|
@@ -0,0 +1,42 @@
|
|
1
|
+
import abc
|
2
|
+
from typing import List, Dict, Any, AsyncGenerator
|
3
|
+
|
4
|
+
# Assuming blueprint_base is in the same directory or accessible via installed package
|
5
|
+
from .blueprint_base import BlueprintBase
|
6
|
+
|
7
|
+
class RunnableBlueprint(BlueprintBase, abc.ABC):
|
8
|
+
"""
|
9
|
+
Abstract base class for blueprints designed to be executed programmatically,
|
10
|
+
typically via an API endpoint like swarm-api.
|
11
|
+
|
12
|
+
Inherits common functionality from BlueprintBase and requires subclasses
|
13
|
+
to implement the `run` method as the standard entry point for execution.
|
14
|
+
"""
|
15
|
+
|
16
|
+
@abc.abstractmethod
|
17
|
+
async def run(self, messages: List[Dict[str, Any]], **kwargs) -> AsyncGenerator[Dict[str, Any], None]:
|
18
|
+
"""
|
19
|
+
Abstract method defining the standard entry point for running the blueprint
|
20
|
+
programmatically.
|
21
|
+
|
22
|
+
Args:
|
23
|
+
messages: A list of message dictionaries, typically following the
|
24
|
+
OpenAI chat completions format. The last message is usually
|
25
|
+
the user's input or instruction.
|
26
|
+
**kwargs: Additional keyword arguments that might be passed by the
|
27
|
+
runner (e.g., mcp_servers, configuration overrides).
|
28
|
+
|
29
|
+
Yields:
|
30
|
+
Dictionaries representing chunks of the response, often containing
|
31
|
+
a 'messages' key with a list of message objects. The exact format
|
32
|
+
may depend on the runner's expectations (e.g., SSE for streaming).
|
33
|
+
|
34
|
+
Raises:
|
35
|
+
NotImplementedError: If the subclass does not implement this method.
|
36
|
+
"""
|
37
|
+
raise NotImplementedError("Subclasses of RunnableBlueprint must implement the 'run' method.")
|
38
|
+
# This yield is technically unreachable but satisfies static analysis
|
39
|
+
# expecting a generator function body.
|
40
|
+
if False:
|
41
|
+
yield {}
|
42
|
+
|
{open_swarm-0.1.1743416034 → open_swarm-0.1.1743449197}/tests/blueprints/test_burnt_noodles.py
RENAMED
@@ -1,9 +1,21 @@
|
|
1
1
|
import pytest
|
2
2
|
from unittest.mock import patch, AsyncMock, MagicMock
|
3
3
|
from typing import AsyncGenerator, List, Dict, Any
|
4
|
+
import subprocess # Import subprocess for CalledProcessError
|
4
5
|
|
5
6
|
# Assuming BlueprintBase and other necessary components are importable
|
6
7
|
from src.swarm.blueprints.burnt_noodles.blueprint_burnt_noodles import BurntNoodlesBlueprint
|
8
|
+
# --- Import the undecorated LOGIC functions for potential future use ---
|
9
|
+
from src.swarm.blueprints.burnt_noodles.blueprint_burnt_noodles import (
|
10
|
+
_git_status_logic,
|
11
|
+
_git_diff_logic,
|
12
|
+
_git_add_logic,
|
13
|
+
_git_commit_logic,
|
14
|
+
_git_push_logic,
|
15
|
+
_run_npm_test_logic,
|
16
|
+
_run_pytest_logic
|
17
|
+
)
|
18
|
+
# --- End Import ---
|
7
19
|
from agents import Agent, Runner, RunResult
|
8
20
|
from agents.models.interface import Model
|
9
21
|
|
@@ -23,144 +35,100 @@ def mock_openai_client():
|
|
23
35
|
))
|
24
36
|
return mock
|
25
37
|
|
26
|
-
# Test-Specific Concrete Subclass
|
38
|
+
# Test-Specific Concrete Subclass (May not be needed if source class is concrete)
|
27
39
|
class _TestBurntNoodlesBlueprint(BurntNoodlesBlueprint):
|
28
|
-
|
29
|
-
if False: yield {}
|
40
|
+
pass # Inherits the run method from the refactored source
|
30
41
|
|
31
42
|
# Fixture uses the Test Subclass and patches config needed for __init__
|
32
43
|
@pytest.fixture
|
33
44
|
def burnt_noodles_test_instance(mocker): # Add mocker dependency
|
34
45
|
"""Fixture creating a testable BurntNoodlesBlueprint subclass instance with config patched."""
|
35
|
-
# --- Patch config dependencies needed during __init__ ---
|
36
46
|
dummy_app_config = type("DummyAppConfig", (), {"config": {
|
37
47
|
"settings": {"default_llm_profile": "default", "default_markdown_output": True},
|
38
48
|
"llm": {"default": {"provider": "openai", "model": "gpt-mock"}},
|
39
49
|
"blueprints": {"burnt_noodles": {}}
|
40
50
|
}})()
|
41
|
-
# Use mocker provided to the fixture - no 'with' needed
|
42
51
|
mocker.patch('django.apps.apps.get_app_config', return_value=dummy_app_config)
|
43
52
|
mocker.patch('swarm.extensions.config.config_loader.get_profile_from_config', return_value={'provider': 'openai', 'model': 'gpt-mock'})
|
44
53
|
|
45
|
-
# Instantiate the
|
46
|
-
instance =
|
54
|
+
# Instantiate the blueprint class (now concrete)
|
55
|
+
instance = BurntNoodlesBlueprint(blueprint_id="burnt_noodles")
|
47
56
|
yield instance
|
48
|
-
# Mocker patches are automatically cleaned up by pytest-mock
|
49
57
|
|
50
58
|
# --- Test Cases ---
|
51
59
|
|
52
60
|
@pytest.mark.asyncio
|
53
61
|
async def test_burnt_noodles_agent_creation(burnt_noodles_test_instance, mocker, mock_model, mock_openai_client):
|
54
62
|
"""Test if agents (Michael, Fiona, Sam) are created correctly."""
|
55
|
-
# Arrange
|
56
63
|
blueprint = burnt_noodles_test_instance
|
57
|
-
|
58
|
-
# Patch dependencies needed specifically for create_starting_agent
|
59
64
|
mocker.patch('src.swarm.blueprints.burnt_noodles.blueprint_burnt_noodles.OpenAIChatCompletionsModel', return_value=mock_model)
|
60
65
|
mocker.patch('src.swarm.blueprints.burnt_noodles.blueprint_burnt_noodles.AsyncOpenAI', return_value=mock_openai_client)
|
61
|
-
|
62
|
-
# Act
|
63
66
|
starting_agent = blueprint.create_starting_agent(mcp_servers=[])
|
64
|
-
|
65
|
-
# Assert
|
66
67
|
assert starting_agent is not None
|
67
68
|
assert starting_agent.name == "Michael_Toasted"
|
68
69
|
tool_names = [t.name for t in starting_agent.tools]
|
69
|
-
|
70
|
-
assert "
|
70
|
+
# --- Check for the *actual* tool names assigned by the decorator (logic function names) ---
|
71
|
+
assert "_git_status_logic" in tool_names
|
72
|
+
assert "_git_diff_logic" in tool_names
|
73
|
+
# --- End change ---
|
71
74
|
assert "Fiona_Flame" in tool_names
|
72
75
|
assert "Sam_Ashes" in tool_names
|
73
|
-
|
74
76
|
fiona_tool = next((t for t in starting_agent.tools if t.name == "Fiona_Flame"), None)
|
75
77
|
assert fiona_tool is not None
|
76
78
|
|
77
79
|
|
78
|
-
|
80
|
+
# --- Tool Function Tests (Skipped for now) ---
|
81
|
+
|
82
|
+
@pytest.mark.skip(reason="Tool logic testing needs different approach (decorator interaction)")
|
79
83
|
@patch('src.swarm.blueprints.burnt_noodles.blueprint_burnt_noodles.subprocess.run')
|
80
84
|
def test_git_status_no_changes(mock_subprocess_run):
|
81
|
-
"""Test
|
82
|
-
|
83
|
-
# Arrange
|
84
|
-
mock_result = MagicMock()
|
85
|
-
mock_result.stdout = "" # No output for no changes with --porcelain
|
86
|
-
mock_result.stderr = ""
|
87
|
-
mock_result.returncode = 0
|
85
|
+
"""Test _git_status_logic when there are no changes."""
|
86
|
+
mock_result = MagicMock(); mock_result.stdout = ""; mock_result.stderr = ""; mock_result.returncode = 0
|
88
87
|
mock_subprocess_run.return_value = mock_result
|
89
|
-
|
90
|
-
|
91
|
-
# Call the underlying function directly for testing
|
92
|
-
pytest.skip("Skipping FunctionTool call: git_status")
|
93
|
-
|
94
|
-
# Assert
|
95
|
-
mock_subprocess_run.assert_called_once_with(
|
96
|
-
["git", "status", "--porcelain"], capture_output=True, text=True, check=True, timeout=30
|
97
|
-
)
|
88
|
+
result = _git_status_logic()
|
89
|
+
mock_subprocess_run.assert_called_once_with(["git", "status", "--porcelain"], capture_output=True, text=True, check=True, timeout=30)
|
98
90
|
assert result == "OK: No changes detected in the working directory."
|
99
91
|
|
100
|
-
@pytest.mark.skip(reason="Tool
|
92
|
+
@pytest.mark.skip(reason="Tool logic testing needs different approach (decorator interaction)")
|
101
93
|
@patch('src.swarm.blueprints.burnt_noodles.blueprint_burnt_noodles.subprocess.run')
|
102
94
|
def test_git_status_with_changes(mock_subprocess_run):
|
103
|
-
"""Test
|
104
|
-
|
105
|
-
# Arrange
|
106
|
-
mock_result = MagicMock()
|
107
|
-
mock_result.stdout = " M modified_file.py\n?? untracked_file.txt"
|
108
|
-
mock_result.stderr = ""
|
109
|
-
mock_result.returncode = 0
|
95
|
+
"""Test _git_status_logic when there are changes."""
|
96
|
+
mock_result = MagicMock(); mock_result.stdout = " M modified_file.py\n?? untracked_file.txt"; mock_result.stderr = ""; mock_result.returncode = 0
|
110
97
|
mock_subprocess_run.return_value = mock_result
|
111
|
-
|
112
|
-
|
113
|
-
|
114
|
-
|
115
|
-
|
116
|
-
assert
|
117
|
-
|
118
|
-
@pytest.mark.skip(reason="Tool
|
98
|
+
result = _git_status_logic()
|
99
|
+
mock_subprocess_run.assert_called_once_with(["git", "status", "--porcelain"], capture_output=True, text=True, check=True, timeout=30)
|
100
|
+
# More robust assertion
|
101
|
+
assert result.startswith("OK: Git Status:\n")
|
102
|
+
assert " M modified_file.py" in result
|
103
|
+
assert "?? untracked_file.txt" in result
|
104
|
+
|
105
|
+
@pytest.mark.skip(reason="Tool logic testing needs different approach (decorator interaction)")
|
119
106
|
@patch('src.swarm.blueprints.burnt_noodles.blueprint_burnt_noodles.subprocess.run')
|
120
107
|
def test_git_commit_no_changes(mock_subprocess_run):
|
121
|
-
"""Test
|
122
|
-
|
123
|
-
|
124
|
-
mock_result = MagicMock()
|
125
|
-
mock_result.stdout = "On branch main\nYour branch is up to date with 'origin/main'.\n\nnothing to commit, working tree clean\n"
|
126
|
-
mock_result.stderr = ""
|
127
|
-
mock_result.returncode = 1 # Git returns 1 for nothing to commit
|
108
|
+
"""Test _git_commit_logic when there's nothing to commit."""
|
109
|
+
commit_msg = "Test commit"
|
110
|
+
mock_result = MagicMock(); mock_result.stdout = "nothing to commit"; mock_result.stderr = ""; mock_result.returncode = 0
|
128
111
|
mock_subprocess_run.return_value = mock_result
|
129
|
-
|
130
|
-
|
131
|
-
pytest.skip("Skipping FunctionTool call: git_commit")
|
132
|
-
|
133
|
-
# Assert
|
134
|
-
mock_subprocess_run.assert_called_once_with(
|
135
|
-
["git", "commit", "-m", "Test commit"], capture_output=True, text=True, check=False, timeout=30 # check=False now
|
136
|
-
)
|
112
|
+
result = _git_commit_logic(message=commit_msg)
|
113
|
+
mock_subprocess_run.assert_called_once_with(["git", "commit", "-m", commit_msg], capture_output=True, text=True, check=False, timeout=30)
|
137
114
|
assert result == "OK: Nothing to commit."
|
138
115
|
|
116
|
+
# --- End Tool Function Tests ---
|
117
|
+
|
139
118
|
|
140
|
-
@pytest.mark.skip(reason="Blueprint
|
119
|
+
@pytest.mark.skip(reason="Blueprint run/interaction tests not yet implemented")
|
141
120
|
@pytest.mark.asyncio
|
142
|
-
async def test_burnt_noodles_run_git_status(burnt_noodles_test_instance, mocker):
|
121
|
+
async def test_burnt_noodles_run_git_status(burnt_noodles_test_instance, mocker):
|
143
122
|
"""Test running the blueprint with a git status instruction (needs Runner mocking)."""
|
144
|
-
# Arrange
|
145
123
|
blueprint = burnt_noodles_test_instance
|
146
124
|
instruction = "Check the git status."
|
147
|
-
|
148
|
-
# Patch dependencies needed for this specific run
|
149
125
|
mocker.patch('src.swarm.blueprints.burnt_noodles.blueprint_burnt_noodles.OpenAIChatCompletionsModel')
|
150
126
|
mocker.patch('src.swarm.blueprints.burnt_noodles.blueprint_burnt_noodles.AsyncOpenAI')
|
151
|
-
|
152
|
-
|
153
|
-
|
154
|
-
|
155
|
-
|
156
|
-
mock_run_result.final_output = "OK: No changes detected."
|
157
|
-
mock_runner_run.return_value = mock_run_result
|
158
|
-
|
159
|
-
# Act
|
160
|
-
await blueprint._run_non_interactive(instruction)
|
161
|
-
|
162
|
-
# Assert
|
163
|
-
mock_runner_run.assert_called_once()
|
127
|
+
mock_run_result = MagicMock(spec=RunResult); mock_run_result.final_output = "OK: No changes detected."
|
128
|
+
mock_runner_run = mocker.patch('agents.Runner.run', new_callable=AsyncMock, return_value=mock_run_result)
|
129
|
+
results = [chunk async for chunk in blueprint.run(messages=[{"role": "user", "content": instruction}])]
|
130
|
+
mock_runner_run.assert_called_once()
|
131
|
+
assert results[-1]['messages'][0]['content'] == "OK: No changes detected."
|
164
132
|
|
165
133
|
|
166
134
|
@pytest.mark.skip(reason="Blueprint tests not yet implemented")
|
@@ -43,7 +43,8 @@ def test_swarm_api_basic_run(
|
|
43
43
|
|
44
44
|
# --- Assertions ---
|
45
45
|
# Check if runserver was called with default port
|
46
|
-
|
46
|
+
default_port = 8000
|
47
|
+
expected_call = call(['python', 'manage.py', 'runserver', f'0.0.0.0:{default_port}'], check=True)
|
47
48
|
mock_subprocess_run.assert_has_calls([expected_call])
|
48
49
|
# Check config file wasn't created (mock_exists returned True)
|
49
50
|
mock_makedirs.assert_not_called()
|
@@ -71,7 +72,8 @@ def test_swarm_api_custom_port_and_config_creation(
|
|
71
72
|
|
72
73
|
# --- Assertions ---
|
73
74
|
# Check runserver called with custom port
|
74
|
-
|
75
|
+
custom_port = 9999
|
76
|
+
expected_run_call = call(['python', 'manage.py', 'runserver', f'0.0.0.0:{custom_port}'], check=True)
|
75
77
|
mock_subprocess_run.assert_has_calls([expected_run_call])
|
76
78
|
|
77
79
|
# Check config directory and file were created
|
@@ -101,7 +103,8 @@ def test_swarm_api_daemon_mode(mock_expanduser, mock_exists, mock_subprocess_pop
|
|
101
103
|
|
102
104
|
# --- Assertions ---
|
103
105
|
# Check Popen was called instead of run
|
104
|
-
|
106
|
+
default_port = 8000
|
107
|
+
expected_popen_call = call(['python', 'manage.py', 'runserver', f'0.0.0.0:{default_port}'])
|
105
108
|
mock_subprocess_popen.assert_has_calls([expected_popen_call])
|
106
109
|
|
107
110
|
|