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