open-swarm 0.1.1745275181__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.1745275181.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.1745275181.dist-info/METADATA +0 -874
- open_swarm-0.1.1745275181.dist-info/RECORD +0 -319
- open_swarm-0.1.1745275181.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 -10
- swarm/blueprints/geese/__init__.py +0 -8
- swarm/blueprints/geese/blueprint_geese.py +0 -384
- 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.1745275181.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
@@ -1,125 +0,0 @@
|
|
1
|
-
import os
|
2
|
-
import importlib
|
3
|
-
import importlib.util
|
4
|
-
import inspect
|
5
|
-
import logging # Ensure logging is imported
|
6
|
-
import sys
|
7
|
-
from typing import Dict, Type, Any
|
8
|
-
from pathlib import Path
|
9
|
-
|
10
|
-
# *** Define logger EARLIER ***
|
11
|
-
logger = logging.getLogger(__name__)
|
12
|
-
|
13
|
-
# *** Import the ACTUAL BlueprintBase from the likely correct path ***
|
14
|
-
try:
|
15
|
-
# Adjust this path if BlueprintBase lives elsewhere
|
16
|
-
from swarm.core.blueprint_base import BlueprintBase
|
17
|
-
except ImportError:
|
18
|
-
# This logger call is now safe
|
19
|
-
logger.error("Failed to import BlueprintBase from swarm.core.blueprint_base. Using placeholder.", exc_info=True)
|
20
|
-
# REMOVED DUMMY BlueprintBase to prevent MRO/import bugs. Always import BlueprintBase from swarm.core.blueprint_base
|
21
|
-
|
22
|
-
|
23
|
-
class BlueprintLoadError(Exception):
|
24
|
-
"""Custom exception for errors during blueprint loading."""
|
25
|
-
pass
|
26
|
-
|
27
|
-
def _get_blueprint_name_from_dir(dir_name: str) -> str:
|
28
|
-
"""Converts directory name (e.g., 'blueprint_my_agent') to blueprint name (e.g., 'my_agent')."""
|
29
|
-
prefix = "blueprint_"
|
30
|
-
if dir_name.startswith(prefix):
|
31
|
-
return dir_name[len(prefix):]
|
32
|
-
return dir_name
|
33
|
-
|
34
|
-
def discover_blueprints(blueprint_dir: str) -> Dict[str, Type[BlueprintBase]]:
|
35
|
-
"""
|
36
|
-
Discovers blueprints (subclasses of BlueprintBase) by looking for
|
37
|
-
'blueprint_{name}.py' files within subdirectories of the given blueprint directory.
|
38
|
-
|
39
|
-
Args:
|
40
|
-
blueprint_dir: The path to the directory containing blueprint subdirectories.
|
41
|
-
|
42
|
-
Returns:
|
43
|
-
A dictionary mapping blueprint names to their corresponding class objects.
|
44
|
-
"""
|
45
|
-
logger.info(f"Starting blueprint discovery in directory: {blueprint_dir}")
|
46
|
-
blueprints: Dict[str, Type[BlueprintBase]] = {}
|
47
|
-
base_dir = Path(blueprint_dir).resolve()
|
48
|
-
|
49
|
-
if not base_dir.is_dir():
|
50
|
-
logger.error(f"Blueprint directory not found or is not a directory: {base_dir}")
|
51
|
-
return blueprints
|
52
|
-
|
53
|
-
# Iterate over items inside the base blueprint directory
|
54
|
-
for subdir in base_dir.iterdir():
|
55
|
-
if not subdir.is_dir():
|
56
|
-
continue # Skip files directly under blueprints/
|
57
|
-
|
58
|
-
# Use directory name as blueprint name (e.g., 'echocraft')
|
59
|
-
blueprint_name = subdir.name
|
60
|
-
logger.debug(f"Processing potential blueprint '{blueprint_name}' in directory: {subdir.name}")
|
61
|
-
|
62
|
-
# Look for the specific .py file, e.g., blueprint_echocraft.py
|
63
|
-
py_file_name = f"blueprint_{blueprint_name}.py"
|
64
|
-
py_file_path = subdir / py_file_name
|
65
|
-
|
66
|
-
if not py_file_path.is_file():
|
67
|
-
# Also check for just {blueprint_name}.py if that's a convention
|
68
|
-
alt_py_file_name = f"{blueprint_name}.py"
|
69
|
-
alt_py_file_path = subdir / alt_py_file_name
|
70
|
-
if alt_py_file_path.is_file():
|
71
|
-
py_file_path = alt_py_file_path # Use the alternative path
|
72
|
-
py_file_name = alt_py_file_name
|
73
|
-
logger.debug(f"Found alternative blueprint file: {py_file_name}")
|
74
|
-
else:
|
75
|
-
logger.warning(f"Skipping directory '{subdir.name}': Neither '{py_file_name}' nor '{alt_py_file_name}' found.")
|
76
|
-
continue
|
77
|
-
|
78
|
-
|
79
|
-
# Construct module import path, e.g., blueprints.echocraft.blueprint_echocraft
|
80
|
-
if py_file_path.name.startswith('blueprint_gatcha'):
|
81
|
-
module_import_path = f"swarm.blueprints.gatcha.{py_file_path.stem}"
|
82
|
-
elif py_file_path.name.startswith('blueprint_'):
|
83
|
-
module_import_path = f"swarm.blueprints.{subdir.name}.{py_file_path.stem}"
|
84
|
-
else:
|
85
|
-
continue
|
86
|
-
|
87
|
-
try:
|
88
|
-
# Ensure parent directory is in path
|
89
|
-
parent_dir = str(base_dir.parent)
|
90
|
-
if parent_dir not in sys.path:
|
91
|
-
logger.debug(f"Adding '{parent_dir}' to sys.path for blueprint discovery.")
|
92
|
-
sys.path.insert(0, parent_dir)
|
93
|
-
|
94
|
-
# Create module spec from file path
|
95
|
-
module_spec = importlib.util.spec_from_file_location(module_import_path, py_file_path)
|
96
|
-
|
97
|
-
if module_spec and module_spec.loader:
|
98
|
-
module = importlib.util.module_from_spec(module_spec)
|
99
|
-
sys.modules[module_import_path] = module
|
100
|
-
module_spec.loader.exec_module(module)
|
101
|
-
logger.debug(f"Successfully loaded module: {module_import_path}")
|
102
|
-
|
103
|
-
found_bp_class = None
|
104
|
-
for name, obj in inspect.getmembers(module):
|
105
|
-
if inspect.isclass(obj) and obj.__module__ == module_import_path and issubclass(obj, BlueprintBase) and obj is not BlueprintBase:
|
106
|
-
if found_bp_class:
|
107
|
-
logger.warning(f"Multiple BlueprintBase subclasses found in {py_file_name}. Using the first: {found_bp_class.__name__}.")
|
108
|
-
else:
|
109
|
-
logger.debug(f"Found Blueprint class '{name}' in module '{module_import_path}'")
|
110
|
-
found_bp_class = obj
|
111
|
-
blueprints[blueprint_name] = found_bp_class
|
112
|
-
# break
|
113
|
-
|
114
|
-
if not found_bp_class:
|
115
|
-
logger.warning(f"No BlueprintBase subclass found directly defined in module: {module_import_path}")
|
116
|
-
else:
|
117
|
-
logger.warning(f"Could not create module spec for {py_file_path}")
|
118
|
-
|
119
|
-
except Exception as e:
|
120
|
-
logger.error(f"Error processing blueprint file '{py_file_path}': {e}", exc_info=True)
|
121
|
-
if module_import_path in sys.modules:
|
122
|
-
del sys.modules[module_import_path]
|
123
|
-
|
124
|
-
logger.info(f"Blueprint discovery complete. Found: {list(blueprints.keys())}")
|
125
|
-
return blueprints
|
swarm/core/blueprint_runner.py
DELETED
@@ -1,59 +0,0 @@
|
|
1
|
-
import sys
|
2
|
-
import traceback
|
3
|
-
import types
|
4
|
-
from typing import AsyncGenerator
|
5
|
-
import inspect
|
6
|
-
|
7
|
-
from .blueprint_base import Spinner
|
8
|
-
|
9
|
-
class BlueprintRunner:
|
10
|
-
@staticmethod
|
11
|
-
async def run_agent(agent, instruction, filter_llm_function_calls=True, spinner_enabled=True) -> AsyncGenerator[dict, None]:
|
12
|
-
"""
|
13
|
-
Runs the agent using Runner.run as an async generator or coroutine, with spinner and error handling.
|
14
|
-
Filters out LLM function call outputs if requested.
|
15
|
-
Handles both coroutine and async generator return types.
|
16
|
-
"""
|
17
|
-
from agents import Runner
|
18
|
-
# Only enable spinner if spinner_enabled is True and not in non-interactive mode
|
19
|
-
# (i.e., only if show_intermediate is True)
|
20
|
-
spinner = None
|
21
|
-
if spinner_enabled:
|
22
|
-
# Check for a marker in instruction or a kwarg to disable spinner in non-interactive
|
23
|
-
frame = inspect.currentframe()
|
24
|
-
show_intermediate = False
|
25
|
-
while frame:
|
26
|
-
if 'kwargs' in frame.f_locals and isinstance(frame.f_locals['kwargs'], dict):
|
27
|
-
show_intermediate = frame.f_locals['kwargs'].get('show_intermediate', False)
|
28
|
-
break
|
29
|
-
frame = frame.f_back
|
30
|
-
if show_intermediate:
|
31
|
-
spinner = Spinner()
|
32
|
-
try:
|
33
|
-
if spinner:
|
34
|
-
spinner.start()
|
35
|
-
result = await Runner.run(agent, instruction)
|
36
|
-
# If result is an async generator, iterate over it
|
37
|
-
if isinstance(result, types.AsyncGeneratorType):
|
38
|
-
async for chunk in result:
|
39
|
-
if filter_llm_function_calls:
|
40
|
-
content = chunk.get("content")
|
41
|
-
if content and ("function call" in content or "args" in content):
|
42
|
-
continue
|
43
|
-
yield chunk
|
44
|
-
elif isinstance(result, (list, dict)):
|
45
|
-
# If it's a list of chunks or a single chunk, yield directly
|
46
|
-
if isinstance(result, list):
|
47
|
-
for chunk in result:
|
48
|
-
yield chunk
|
49
|
-
else:
|
50
|
-
yield result
|
51
|
-
elif result is not None:
|
52
|
-
# Fallback: yield as a single chunk
|
53
|
-
yield {"messages": [{"role": "assistant", "content": str(result)}]}
|
54
|
-
except Exception as e:
|
55
|
-
tb = traceback.format_exc()
|
56
|
-
yield {"messages": [{"role": "assistant", "content": f"Error: {e}\n{tb}"}]}
|
57
|
-
finally:
|
58
|
-
if spinner:
|
59
|
-
spinner.stop()
|
swarm/core/blueprint_ux.py
DELETED
@@ -1,109 +0,0 @@
|
|
1
|
-
# UX utilities for Swarm blueprints (stub for legacy/test compatibility)
|
2
|
-
|
3
|
-
class BlueprintUX:
|
4
|
-
def __init__(self, style=None):
|
5
|
-
self.style = style or "default"
|
6
|
-
def box(self, title, content, summary=None, params=None):
|
7
|
-
# Minimal ANSI/emoji box for test compatibility
|
8
|
-
box = f"\033[1;36m┏━ {title} ━\033[0m\n"
|
9
|
-
if params:
|
10
|
-
box += f"\033[1;34m┃ Params: {params}\033[0m\n"
|
11
|
-
if summary:
|
12
|
-
box += f"\033[1;33m┃ {summary}\033[0m\n"
|
13
|
-
for line in content.split('\n'):
|
14
|
-
box += f"┃ {line}\n"
|
15
|
-
box += "┗"+"━"*20
|
16
|
-
return box
|
17
|
-
|
18
|
-
import time
|
19
|
-
import itertools
|
20
|
-
|
21
|
-
# Style presets
|
22
|
-
|
23
|
-
def get_style(style):
|
24
|
-
if style == "serious":
|
25
|
-
return {
|
26
|
-
"border_top": "\033[1;34m╔" + "═"*50 + "╗\033[0m",
|
27
|
-
"border_bottom": "\033[1;34m╚" + "═"*50 + "╝\033[0m",
|
28
|
-
"border_side": "\033[1;34m║\033[0m",
|
29
|
-
"emoji": "🛠️",
|
30
|
-
"spinner": ['Generating.', 'Generating..', 'Generating...', 'Running...'],
|
31
|
-
"fallback": 'Generating... Taking longer than expected',
|
32
|
-
}
|
33
|
-
elif style == "silly":
|
34
|
-
return {
|
35
|
-
"border_top": "\033[1;35m(ノ◕ヮ◕)ノ*:・゚✧" + "~"*40 + "✧゚・: *ヽ(◕ヮ◕ヽ)\033[0m",
|
36
|
-
"border_bottom": "\033[1;35m(づ。◕‿‿◕。)づ" + "~"*40 + "づ(。◕‿‿◕。)づ\033[0m",
|
37
|
-
"border_side": "\033[1;35m~\033[0m",
|
38
|
-
"emoji": "🦆",
|
39
|
-
"spinner": ['Quacking.', 'Quacking..', 'Quacking...', 'Flapping...'],
|
40
|
-
"fallback": 'Quacking... Taking longer than expected',
|
41
|
-
}
|
42
|
-
else:
|
43
|
-
return get_style("serious")
|
44
|
-
|
45
|
-
class BlueprintUXImproved:
|
46
|
-
def __init__(self, style="serious"):
|
47
|
-
self.style = style
|
48
|
-
self._style_conf = get_style(style)
|
49
|
-
self._spinner_cycle = itertools.cycle(self._style_conf["spinner"])
|
50
|
-
self._spinner_start = None
|
51
|
-
|
52
|
-
def spinner(self, state_idx, taking_long=False):
|
53
|
-
if taking_long:
|
54
|
-
return self._style_conf["fallback"]
|
55
|
-
spinner_states = self._style_conf["spinner"]
|
56
|
-
return spinner_states[state_idx % len(spinner_states)]
|
57
|
-
|
58
|
-
def summary(self, op_type, result_count, params):
|
59
|
-
# Enhanced: pretty param formatting
|
60
|
-
param_str = ', '.join(f'{k}={v!r}' for k, v in (params or {}).items()) if params else 'None'
|
61
|
-
return f"{op_type} | Results: {result_count} | Params: {param_str}"
|
62
|
-
|
63
|
-
def progress(self, current, total=None):
|
64
|
-
if total:
|
65
|
-
return f"Processed {current}/{total} lines..."
|
66
|
-
return f"Processed {current} lines..."
|
67
|
-
|
68
|
-
def code_vs_semantic(self, result_type, results):
|
69
|
-
if result_type == "code":
|
70
|
-
header = "[Code Search Results]"
|
71
|
-
elif result_type == "semantic":
|
72
|
-
header = "[Semantic Search Results]"
|
73
|
-
else:
|
74
|
-
header = "[Results]"
|
75
|
-
# Enhanced: visually distinct divider
|
76
|
-
divider = "\n" + ("=" * 40) + "\n"
|
77
|
-
return f"{header}{divider}" + "\n".join(results)
|
78
|
-
|
79
|
-
def ansi_emoji_box(self, title, content, summary=None, params=None, result_count=None, op_type=None, style=None, color=None, status=None):
|
80
|
-
"""
|
81
|
-
Unified ANSI/emoji box for search/analysis/fileops results.
|
82
|
-
Summarizes: operation, result count, params, and allows for periodic updates.
|
83
|
-
Supports color and status for advanced UX.
|
84
|
-
"""
|
85
|
-
style_conf = get_style(style or self.style)
|
86
|
-
# Color/status logic
|
87
|
-
color_map = {
|
88
|
-
"success": "92", # green
|
89
|
-
"info": "94", # blue
|
90
|
-
"warning": "93", # yellow
|
91
|
-
"error": "91", # red
|
92
|
-
None: "94", # default blue
|
93
|
-
}
|
94
|
-
ansi_color = color_map.get(status, color_map[None])
|
95
|
-
box = f"\033[{ansi_color}m" + style_conf["border_top"] + "\033[0m\n"
|
96
|
-
box += f"\033[{ansi_color}m{style_conf['border_side']} {style_conf['emoji']} {title}"
|
97
|
-
if op_type:
|
98
|
-
box += f" | {op_type}"
|
99
|
-
if result_count is not None:
|
100
|
-
box += f" | Results: {result_count}"
|
101
|
-
box += "\033[0m\n"
|
102
|
-
if params:
|
103
|
-
box += f"\033[{ansi_color}m{style_conf['border_side']} Params: {params}\033[0m\n"
|
104
|
-
if summary:
|
105
|
-
box += f"\033[{ansi_color}m{style_conf['border_side']} {summary}\033[0m\n"
|
106
|
-
for line in content.split('\n'):
|
107
|
-
box += f"\033[{ansi_color}m{style_conf['border_side']} {line}\033[0m\n"
|
108
|
-
box += f"\033[{ansi_color}m" + style_conf["border_bottom"] + "\033[0m"
|
109
|
-
return box
|
swarm/core/build_launchers.py
DELETED
@@ -1,15 +0,0 @@
|
|
1
|
-
#!/usr/bin/env python3
|
2
|
-
import PyInstaller.__main__
|
3
|
-
|
4
|
-
def build_executable(script, output_name):
|
5
|
-
PyInstaller.__main__.run([
|
6
|
-
script,
|
7
|
-
"--onefile",
|
8
|
-
"--name", output_name,
|
9
|
-
])
|
10
|
-
|
11
|
-
if __name__ == "__main__":
|
12
|
-
# build echocraft first (already done), now build rue_code
|
13
|
-
build_executable("src/swarm/blueprints/rue_code/blueprint_rue_code.py", "ruecode-blueprint")
|
14
|
-
# Uncomment below to build suggestion after verifying disk space
|
15
|
-
# build_executable("src/swarm/blueprints/suggestion/blueprint_suggestion.py", "suggestion-blueprint")
|
swarm/core/cli/__init__.py
DELETED
@@ -1 +0,0 @@
|
|
1
|
-
|
@@ -1 +0,0 @@
|
|
1
|
-
|
@@ -1,14 +0,0 @@
|
|
1
|
-
def interactive_shell():
|
2
|
-
print("Welcome to Swarm Core CLI Interactive Shell!")
|
3
|
-
print("Type 'help' for available commands.")
|
4
|
-
while True:
|
5
|
-
try:
|
6
|
-
cmd = input("swarm> ").strip()
|
7
|
-
if cmd in ("exit", "quit"): break
|
8
|
-
elif cmd == "help":
|
9
|
-
print("Available commands: list, edit-config, validate-env, validate-envvars, blueprint-manage, config-manage")
|
10
|
-
elif cmd:
|
11
|
-
print(f"Command '{cmd}' not recognized (type 'help').")
|
12
|
-
except KeyboardInterrupt:
|
13
|
-
print("\nExiting shell.")
|
14
|
-
break
|
swarm/core/cli/main.py
DELETED
@@ -1,50 +0,0 @@
|
|
1
|
-
"""
|
2
|
-
Main entry point for Swarm CLI (core).
|
3
|
-
"""
|
4
|
-
|
5
|
-
import argparse
|
6
|
-
import os
|
7
|
-
from swarm.core.cli.utils.discover_commands import discover_commands
|
8
|
-
from swarm.core.cli.interactive_shell import interactive_shell
|
9
|
-
|
10
|
-
COMMANDS_DIR = os.path.join(os.path.dirname(__file__), "commands")
|
11
|
-
|
12
|
-
USER_FRIENDLY_COMMANDS = {
|
13
|
-
"list": "list_blueprints",
|
14
|
-
"edit-config": "edit_config",
|
15
|
-
"validate-env": "validate_env",
|
16
|
-
"validate-envvars": "validate_envvars",
|
17
|
-
"blueprint-manage": "blueprint_management",
|
18
|
-
"config-manage": "config_management",
|
19
|
-
}
|
20
|
-
|
21
|
-
def parse_args(commands):
|
22
|
-
"""Parse CLI arguments dynamically with user-friendly names."""
|
23
|
-
parser = argparse.ArgumentParser(description="Swarm CLI Utility (core)")
|
24
|
-
subparsers = parser.add_subparsers(dest="command")
|
25
|
-
|
26
|
-
for cmd_name, metadata in commands.items():
|
27
|
-
subparsers.add_parser(cmd_name, help=metadata["description"])
|
28
|
-
|
29
|
-
return parser.parse_args()
|
30
|
-
|
31
|
-
def main():
|
32
|
-
# Discover commands using user-friendly mapping
|
33
|
-
raw_commands = discover_commands(COMMANDS_DIR)
|
34
|
-
commands = {}
|
35
|
-
for user_cmd, internal_cmd in USER_FRIENDLY_COMMANDS.items():
|
36
|
-
if internal_cmd in raw_commands:
|
37
|
-
commands[user_cmd] = raw_commands[internal_cmd]
|
38
|
-
args = parse_args(commands)
|
39
|
-
|
40
|
-
if args.command:
|
41
|
-
command = commands.get(args.command, {}).get("execute")
|
42
|
-
if command:
|
43
|
-
command()
|
44
|
-
else:
|
45
|
-
print(f"Command '{args.command}' is not executable.")
|
46
|
-
else:
|
47
|
-
interactive_shell()
|
48
|
-
|
49
|
-
if __name__ == "__main__":
|
50
|
-
main()
|
swarm/core/cli/utils/__init__.py
DELETED
@@ -1 +0,0 @@
|
|
1
|
-
|
@@ -1,18 +0,0 @@
|
|
1
|
-
import os
|
2
|
-
import importlib.util
|
3
|
-
import inspect
|
4
|
-
|
5
|
-
def discover_commands(commands_dir):
|
6
|
-
commands = {}
|
7
|
-
for filename in os.listdir(commands_dir):
|
8
|
-
if filename.endswith('.py') and not filename.startswith('__'):
|
9
|
-
module_name = filename[:-3]
|
10
|
-
module_path = os.path.join(commands_dir, filename)
|
11
|
-
spec = importlib.util.spec_from_file_location(f'swarm.core.cli.commands.{module_name}', module_path)
|
12
|
-
module = importlib.util.module_from_spec(spec)
|
13
|
-
spec.loader.exec_module(module)
|
14
|
-
# Look for an 'execute' function
|
15
|
-
if hasattr(module, 'execute'):
|
16
|
-
desc = inspect.getdoc(module.execute) or f"Run {module_name} command."
|
17
|
-
commands[module_name] = {"execute": module.execute, "description": desc}
|
18
|
-
return commands
|
swarm/core/config_loader.py
DELETED
@@ -1,122 +0,0 @@
|
|
1
|
-
import json
|
2
|
-
import logging
|
3
|
-
import os
|
4
|
-
from pathlib import Path
|
5
|
-
from typing import Any, Dict, Optional, Union
|
6
|
-
|
7
|
-
from dotenv import load_dotenv
|
8
|
-
|
9
|
-
logger = logging.getLogger("swarm.config")
|
10
|
-
|
11
|
-
def _substitute_env_vars(value: Any) -> Any:
|
12
|
-
import os
|
13
|
-
if isinstance(value, str):
|
14
|
-
# Always expand env vars in any string
|
15
|
-
return os.path.expandvars(value)
|
16
|
-
elif isinstance(value, list):
|
17
|
-
return [_substitute_env_vars(item) for item in value]
|
18
|
-
elif isinstance(value, dict):
|
19
|
-
return {k: _substitute_env_vars(v) for k, v in value.items()}
|
20
|
-
return value
|
21
|
-
|
22
|
-
def load_environment(project_root: Path):
|
23
|
-
"""Loads environment variables from a `.env` file located at the project root."""
|
24
|
-
dotenv_path = project_root / ".env"
|
25
|
-
logger.debug(f"Checking for .env file at: {dotenv_path}")
|
26
|
-
try:
|
27
|
-
if dotenv_path.is_file():
|
28
|
-
loaded = load_dotenv(dotenv_path=dotenv_path, override=True)
|
29
|
-
if loaded:
|
30
|
-
logger.debug(f".env file Loaded/Overridden at: {dotenv_path}")
|
31
|
-
else:
|
32
|
-
logger.debug(f"No .env file found at {dotenv_path}.")
|
33
|
-
except Exception as e:
|
34
|
-
logger.error(f"Error loading .env file '{dotenv_path}': {e}", exc_info=logger.level <= logging.DEBUG)
|
35
|
-
|
36
|
-
def load_full_configuration(
|
37
|
-
blueprint_class_name: str,
|
38
|
-
default_config_path: Path,
|
39
|
-
config_path_override: Optional[Union[str, Path]] = None,
|
40
|
-
profile_override: Optional[str] = None,
|
41
|
-
cli_config_overrides: Optional[Dict[str, Any]] = None,
|
42
|
-
) -> Dict[str, Any]:
|
43
|
-
"""
|
44
|
-
Loads and merges configuration settings from base file, blueprint specifics, profiles, and CLI overrides.
|
45
|
-
|
46
|
-
Args:
|
47
|
-
blueprint_class_name (str): The name of the blueprint class (e.g., "MyBlueprint").
|
48
|
-
default_config_path (Path): The default path to the swarm_config.json file.
|
49
|
-
config_path_override (Optional[Union[str, Path]]): Path specified via CLI argument.
|
50
|
-
profile_override (Optional[str]): Profile specified via CLI argument.
|
51
|
-
cli_config_overrides (Optional[Dict[str, Any]]): Overrides provided via CLI argument.
|
52
|
-
|
53
|
-
Returns:
|
54
|
-
Dict[str, Any]: The final, merged configuration dictionary.
|
55
|
-
|
56
|
-
Raises:
|
57
|
-
ValueError: If the configuration file has JSON errors or cannot be read.
|
58
|
-
FileNotFoundError: If a specific config_path_override is given but the file doesn't exist.
|
59
|
-
"""
|
60
|
-
config_path = Path(config_path_override) if config_path_override else default_config_path
|
61
|
-
logger.debug(f"Attempting to load base configuration from: {config_path}")
|
62
|
-
base_config = {}
|
63
|
-
if config_path.is_file():
|
64
|
-
try:
|
65
|
-
with open(config_path, "r", encoding="utf-8") as f:
|
66
|
-
base_config = json.load(f)
|
67
|
-
logger.debug(f"Successfully loaded base configuration from: {config_path}")
|
68
|
-
except json.JSONDecodeError as e:
|
69
|
-
raise ValueError(f"Config Error: Failed to parse JSON in {config_path}: {e}") from e
|
70
|
-
except Exception as e:
|
71
|
-
raise ValueError(f"Config Error: Failed to read {config_path}: {e}") from e
|
72
|
-
else:
|
73
|
-
if config_path_override:
|
74
|
-
raise FileNotFoundError(f"Configuration Error: Specified config file not found: {config_path}")
|
75
|
-
else:
|
76
|
-
logger.warning(f"Default configuration file not found at {config_path}. Proceeding without base configuration.")
|
77
|
-
|
78
|
-
# 1. Start with base defaults
|
79
|
-
final_config = base_config.get("defaults", {}).copy()
|
80
|
-
logger.debug(f"Applied base defaults. Keys: {list(final_config.keys())}")
|
81
|
-
|
82
|
-
# 2. Merge base llm and mcpServers sections
|
83
|
-
if "llm" in base_config:
|
84
|
-
final_config.setdefault("llm", {}).update(base_config["llm"])
|
85
|
-
logger.debug("Merged base 'llm'.")
|
86
|
-
if "mcpServers" in base_config:
|
87
|
-
final_config.setdefault("mcpServers", {}).update(base_config["mcpServers"])
|
88
|
-
logger.debug("Merged base 'mcpServers'.")
|
89
|
-
|
90
|
-
# 3. Merge blueprint-specific settings
|
91
|
-
blueprint_settings = base_config.get("blueprints", {}).get(blueprint_class_name, {})
|
92
|
-
if blueprint_settings:
|
93
|
-
final_config.update(blueprint_settings)
|
94
|
-
logger.debug(f"Merged BP '{blueprint_class_name}' settings. Keys: {list(blueprint_settings.keys())}")
|
95
|
-
|
96
|
-
# 4. Determine and merge profile settings
|
97
|
-
# Priority: CLI > Blueprint Specific > Base Defaults > "default"
|
98
|
-
profile_in_bp_settings = blueprint_settings.get("default_profile")
|
99
|
-
profile_in_base_defaults = base_config.get("defaults", {}).get("default_profile")
|
100
|
-
profile_to_use = profile_override or profile_in_bp_settings or profile_in_base_defaults or "default"
|
101
|
-
logger.debug(f"Using profile: '{profile_to_use}'")
|
102
|
-
profile_settings = base_config.get("profiles", {}).get(profile_to_use, {})
|
103
|
-
if profile_settings:
|
104
|
-
final_config.update(profile_settings)
|
105
|
-
logger.debug(f"Merged profile '{profile_to_use}'. Keys: {list(profile_settings.keys())}")
|
106
|
-
elif profile_to_use != "default" and (profile_override or profile_in_bp_settings or profile_in_base_defaults):
|
107
|
-
logger.warning(f"Profile '{profile_to_use}' requested but not found.")
|
108
|
-
|
109
|
-
# 5. Merge CLI overrides (highest priority)
|
110
|
-
if cli_config_overrides:
|
111
|
-
final_config.update(cli_config_overrides)
|
112
|
-
logger.debug(f"Merged CLI overrides. Keys: {list(cli_config_overrides.keys())}")
|
113
|
-
|
114
|
-
# Ensure top-level keys exist
|
115
|
-
final_config.setdefault("llm", {})
|
116
|
-
final_config.setdefault("mcpServers", {})
|
117
|
-
|
118
|
-
# 6. Substitute environment variables in the final config
|
119
|
-
final_config = _substitute_env_vars(final_config)
|
120
|
-
logger.debug("Applied final env var substitution.")
|
121
|
-
|
122
|
-
return final_config
|