open-swarm 0.1.1745275181__py3-none-any.whl → 0.1.1748636295__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.1748636295.dist-info/METADATA +257 -0
- open_swarm-0.1.1748636295.dist-info/RECORD +89 -0
- {open_swarm-0.1.1745275181.dist-info → open_swarm-0.1.1748636295.dist-info}/WHEEL +2 -1
- open_swarm-0.1.1748636295.dist-info/entry_points.txt +3 -0
- open_swarm-0.1.1748636295.dist-info/top_level.txt +1 -0
- swarm/__init__.py +2 -0
- swarm/agent/agent.py +49 -0
- swarm/auth.py +48 -113
- swarm/consumers.py +0 -19
- swarm/core.py +411 -0
- swarm/extensions/blueprint/__init__.py +16 -30
- swarm/extensions/blueprint/agent_utils.py +45 -0
- swarm/extensions/blueprint/blueprint_base.py +562 -0
- swarm/extensions/blueprint/blueprint_discovery.py +112 -0
- swarm/extensions/blueprint/django_utils.py +79 -181
- swarm/extensions/blueprint/interactive_mode.py +72 -67
- swarm/extensions/blueprint/output_utils.py +82 -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 +345 -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/extensions/mcp/__init__.py +1 -0
- swarm/extensions/mcp/cache_utils.py +32 -0
- swarm/extensions/mcp/mcp_client.py +233 -0
- swarm/extensions/mcp/mcp_tool_provider.py +135 -0
- swarm/extensions/mcp/mcp_utils.py +260 -0
- swarm/llm/chat_completion.py +166 -0
- swarm/serializers.py +5 -96
- swarm/settings.py +133 -85
- swarm/types.py +91 -0
- 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 +76 -236
- swarm/views/core_views.py +87 -80
- swarm/views/model_views.py +121 -64
- swarm/views/utils.py +439 -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/agent_utils.py +0 -21
- 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.1748636295.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,384 +0,0 @@
|
|
1
|
-
# --- Content for src/swarm/blueprints/echocraft/blueprint_echocraft.py ---
|
2
|
-
import logging
|
3
|
-
from typing import Optional
|
4
|
-
from pathlib import Path
|
5
|
-
from typing import List, Dict, Any, AsyncGenerator
|
6
|
-
import uuid # Import uuid to generate IDs
|
7
|
-
import time # Import time for timestamp
|
8
|
-
import os
|
9
|
-
from datetime import datetime
|
10
|
-
import pytz
|
11
|
-
|
12
|
-
from swarm.core.blueprint_base import BlueprintBase
|
13
|
-
from agents import function_tool
|
14
|
-
# Patch: Expose underlying fileops functions for direct testing
|
15
|
-
class PatchedFunctionTool:
|
16
|
-
def __init__(self, func, name):
|
17
|
-
self.func = func
|
18
|
-
self.name = name
|
19
|
-
|
20
|
-
def read_file(path: str) -> str:
|
21
|
-
try:
|
22
|
-
with open(path, 'r') as f:
|
23
|
-
return f.read()
|
24
|
-
except Exception as e:
|
25
|
-
return f"ERROR: {e}"
|
26
|
-
def write_file(path: str, content: str) -> str:
|
27
|
-
try:
|
28
|
-
with open(path, 'w') as f:
|
29
|
-
f.write(content)
|
30
|
-
return "OK: file written"
|
31
|
-
except Exception as e:
|
32
|
-
return f"ERROR: {e}"
|
33
|
-
def list_files(directory: str = '.') -> str:
|
34
|
-
try:
|
35
|
-
return '\n'.join(os.listdir(directory))
|
36
|
-
except Exception as e:
|
37
|
-
return f"ERROR: {e}"
|
38
|
-
def execute_shell_command(command: str) -> str:
|
39
|
-
"""
|
40
|
-
Executes a shell command and returns its stdout and stderr.
|
41
|
-
Timeout is configurable via SWARM_COMMAND_TIMEOUT (default: 60s).
|
42
|
-
"""
|
43
|
-
logger.info(f"Executing shell command: {command}")
|
44
|
-
try:
|
45
|
-
import os
|
46
|
-
timeout = int(os.getenv("SWARM_COMMAND_TIMEOUT", "60"))
|
47
|
-
result = subprocess.run(command, shell=True, capture_output=True, text=True, timeout=timeout)
|
48
|
-
output = f"Exit Code: {result.returncode}\n"
|
49
|
-
if result.stdout:
|
50
|
-
output += f"STDOUT:\n{result.stdout}\n"
|
51
|
-
if result.stderr:
|
52
|
-
output += f"STDERR:\n{result.stderr}\n"
|
53
|
-
logger.info(f"Command finished. Exit Code: {result.returncode}")
|
54
|
-
return output.strip()
|
55
|
-
except subprocess.TimeoutExpired:
|
56
|
-
logger.error(f"Command timed out: {command}")
|
57
|
-
return f"Error: Command timed out after {os.getenv('SWARM_COMMAND_TIMEOUT', '60')} seconds."
|
58
|
-
except Exception as e:
|
59
|
-
logger.error(f"Error executing command '{command}': {e}", exc_info=True)
|
60
|
-
return f"Error executing command: {e}"
|
61
|
-
read_file_tool = PatchedFunctionTool(read_file, 'read_file')
|
62
|
-
write_file_tool = PatchedFunctionTool(write_file, 'write_file')
|
63
|
-
list_files_tool = PatchedFunctionTool(list_files, 'list_files')
|
64
|
-
execute_shell_command_tool = PatchedFunctionTool(execute_shell_command, 'execute_shell_command')
|
65
|
-
|
66
|
-
logger = logging.getLogger(__name__)
|
67
|
-
|
68
|
-
# Last swarm update: 2024-03-07T14:30:00Z (UTC)
|
69
|
-
# Spinner UX enhancement (Open Swarm TODO)
|
70
|
-
SPINNER_STATES = ['Generating.', 'Generating..', 'Generating...', 'Running...']
|
71
|
-
|
72
|
-
"""
|
73
|
-
EchoCraft Blueprint
|
74
|
-
|
75
|
-
Viral docstring update: Operational as of {} (UTC).
|
76
|
-
Self-healing, fileops-enabled, swarm-scalable.
|
77
|
-
"""
|
78
|
-
|
79
|
-
# [Swarm Propagation] Next Blueprint: rue_code
|
80
|
-
# rue_code key vars: logger, project_root, src_path
|
81
|
-
# rue_code guard: if src_path not in sys.path: sys.path.insert(0, src_path)
|
82
|
-
# rue_code debug: logger.debug("RueCode agent created: Rue (Coordinator)")
|
83
|
-
# rue_code error handling: try/except ImportError with sys.exit(1)
|
84
|
-
|
85
|
-
class EchoCraftBlueprint(BlueprintBase):
|
86
|
-
def __init__(self, blueprint_id: str = "echocraft", config=None, config_path=None, **kwargs):
|
87
|
-
super().__init__(blueprint_id, config=config, config_path=config_path, **kwargs)
|
88
|
-
self.blueprint_id = blueprint_id
|
89
|
-
self.config_path = config_path
|
90
|
-
self._config = config if config is not None else {}
|
91
|
-
self._llm_profile_name = None
|
92
|
-
self._llm_profile_data = None
|
93
|
-
self._markdown_output = None
|
94
|
-
# Add other attributes as needed for Echocraft
|
95
|
-
# ...
|
96
|
-
|
97
|
-
"""
|
98
|
-
A simple blueprint that echoes the last user message.
|
99
|
-
Used for testing and demonstrating basic blueprint structure.
|
100
|
-
"""
|
101
|
-
|
102
|
-
# No specific __init__ needed beyond the base class unless adding more params
|
103
|
-
# def __init__(self, blueprint_id: str, **kwargs):
|
104
|
-
# super().__init__(blueprint_id=blueprint_id, **kwargs)
|
105
|
-
# logger.info(f"EchoCraftBlueprint '{self.blueprint_id}' initialized.")
|
106
|
-
|
107
|
-
# --- FileOps Tool Logic Definitions ---
|
108
|
-
def read_file(path: str) -> str:
|
109
|
-
try:
|
110
|
-
with open(path, 'r') as f:
|
111
|
-
return f.read()
|
112
|
-
except Exception as e:
|
113
|
-
return f"ERROR: {e}"
|
114
|
-
def write_file(path: str, content: str) -> str:
|
115
|
-
try:
|
116
|
-
with open(path, 'w') as f:
|
117
|
-
f.write(content)
|
118
|
-
return "OK: file written"
|
119
|
-
except Exception as e:
|
120
|
-
return f"ERROR: {e}"
|
121
|
-
def list_files(directory: str = '.') -> str:
|
122
|
-
try:
|
123
|
-
return '\n'.join(os.listdir(directory))
|
124
|
-
except Exception as e:
|
125
|
-
return f"ERROR: {e}"
|
126
|
-
def execute_shell_command(self, command: str) -> str:
|
127
|
-
"""
|
128
|
-
Executes a shell command and returns its stdout and stderr.
|
129
|
-
Timeout is configurable via SWARM_COMMAND_TIMEOUT (default: 60s).
|
130
|
-
"""
|
131
|
-
logger.info(f"Executing shell command: {command}")
|
132
|
-
try:
|
133
|
-
import os
|
134
|
-
timeout = int(os.getenv("SWARM_COMMAND_TIMEOUT", "60"))
|
135
|
-
result = subprocess.run(command, shell=True, capture_output=True, text=True, timeout=timeout)
|
136
|
-
output = f"Exit Code: {result.returncode}\n"
|
137
|
-
if result.stdout:
|
138
|
-
output += f"STDOUT:\n{result.stdout}\n"
|
139
|
-
if result.stderr:
|
140
|
-
output += f"STDERR:\n{result.stderr}\n"
|
141
|
-
logger.info(f"Command finished. Exit Code: {result.returncode}")
|
142
|
-
return output.strip()
|
143
|
-
except subprocess.TimeoutExpired:
|
144
|
-
logger.error(f"Command timed out: {command}")
|
145
|
-
return f"Error: Command timed out after {os.getenv('SWARM_COMMAND_TIMEOUT', '60')} seconds."
|
146
|
-
except Exception as e:
|
147
|
-
logger.error(f"Error executing command '{command}': {e}", exc_info=True)
|
148
|
-
return f"Error executing command: {e}"
|
149
|
-
read_file_tool = PatchedFunctionTool(read_file, 'read_file')
|
150
|
-
write_file_tool = PatchedFunctionTool(write_file, 'write_file')
|
151
|
-
list_files_tool = PatchedFunctionTool(list_files, 'list_files')
|
152
|
-
execute_shell_command_tool = PatchedFunctionTool(execute_shell_command, 'execute_shell_command')
|
153
|
-
|
154
|
-
async def _original_run(self, messages: List[Dict[str, Any]], **kwargs: Any) -> AsyncGenerator[Dict[str, Any], None]:
|
155
|
-
"""
|
156
|
-
Echoes the content of the last message with role 'user'.
|
157
|
-
Yields a final message in OpenAI ChatCompletion format.
|
158
|
-
"""
|
159
|
-
logger.info(f"EchoCraftBlueprint run called with {len(messages)} messages.")
|
160
|
-
|
161
|
-
# Ensure LLM profile is initialized for test compatibility
|
162
|
-
if self._llm_profile_name is None:
|
163
|
-
self._llm_profile_name = self.config.get("llm_profile", "default")
|
164
|
-
|
165
|
-
last_user_message_content = "No user message found."
|
166
|
-
for msg in reversed(messages):
|
167
|
-
if msg.get("role") == "user":
|
168
|
-
last_user_message_content = msg.get("content", "(empty content)")
|
169
|
-
logger.debug(f"Found last user message: {last_user_message_content}")
|
170
|
-
break
|
171
|
-
|
172
|
-
echo_content = f"Echo: {last_user_message_content}"
|
173
|
-
logger.info(f"EchoCraftBlueprint yielding: {echo_content}")
|
174
|
-
|
175
|
-
# --- Format the final output as an OpenAI ChatCompletion object ---
|
176
|
-
completion_id = f"chatcmpl-echo-{uuid.uuid4()}"
|
177
|
-
created_timestamp = int(time.time())
|
178
|
-
|
179
|
-
final_message_chunk = {
|
180
|
-
"id": completion_id,
|
181
|
-
"object": "chat.completion",
|
182
|
-
"created": created_timestamp,
|
183
|
-
"model": self.llm_profile_name, # Use profile name as model identifier
|
184
|
-
"choices": [
|
185
|
-
{
|
186
|
-
"index": 0,
|
187
|
-
"message": {
|
188
|
-
"role": "assistant",
|
189
|
-
"content": echo_content,
|
190
|
-
},
|
191
|
-
"finish_reason": "stop",
|
192
|
-
"logprobs": None, # Add null logprobs if needed
|
193
|
-
}
|
194
|
-
],
|
195
|
-
# Add usage stats if desired/possible
|
196
|
-
# "usage": {
|
197
|
-
# "prompt_tokens": 0,
|
198
|
-
# "completion_tokens": 0,
|
199
|
-
# "total_tokens": 0
|
200
|
-
# }
|
201
|
-
}
|
202
|
-
yield final_message_chunk
|
203
|
-
# --- End formatting change ---
|
204
|
-
|
205
|
-
logger.info("EchoCraftBlueprint run finished.")
|
206
|
-
|
207
|
-
async def run(self, messages: List[Dict[str, Any]], **kwargs: Any) -> AsyncGenerator[Dict[str, Any], None]:
|
208
|
-
last_result = None
|
209
|
-
async for result in self._original_run(messages):
|
210
|
-
last_result = result
|
211
|
-
yield result
|
212
|
-
if last_result is not None:
|
213
|
-
await self.reflect_and_learn(messages, last_result)
|
214
|
-
|
215
|
-
async def reflect_and_learn(self, messages, result):
|
216
|
-
log = {
|
217
|
-
'task': messages,
|
218
|
-
'result': result,
|
219
|
-
'reflection': 'Success' if self.success_criteria(result) else 'Needs improvement',
|
220
|
-
'alternatives': self.consider_alternatives(messages, result),
|
221
|
-
'swarm_lessons': self.query_swarm_knowledge(messages)
|
222
|
-
}
|
223
|
-
self.write_to_swarm_log(log)
|
224
|
-
|
225
|
-
def success_criteria(self, result):
|
226
|
-
if not result or (isinstance(result, dict) and 'error' in result):
|
227
|
-
return False
|
228
|
-
if isinstance(result, list) and result and 'error' in result[0].get('messages', [{}])[0].get('content', '').lower():
|
229
|
-
return False
|
230
|
-
return True
|
231
|
-
|
232
|
-
def consider_alternatives(self, messages, result):
|
233
|
-
alternatives = []
|
234
|
-
if not self.success_criteria(result):
|
235
|
-
alternatives.append('Try echoing a different message.')
|
236
|
-
alternatives.append('Use a fallback echo agent.')
|
237
|
-
else:
|
238
|
-
alternatives.append('Add sentiment analysis to the echo.')
|
239
|
-
return alternatives
|
240
|
-
|
241
|
-
def query_swarm_knowledge(self, messages):
|
242
|
-
import json, os
|
243
|
-
path = os.path.join(os.path.dirname(__file__), '../../../swarm_knowledge.json')
|
244
|
-
if not os.path.exists(path):
|
245
|
-
return []
|
246
|
-
with open(path, 'r') as f:
|
247
|
-
knowledge = json.load(f)
|
248
|
-
task_str = json.dumps(messages)
|
249
|
-
return [entry for entry in knowledge if entry.get('task_str') == task_str]
|
250
|
-
|
251
|
-
def write_to_swarm_log(self, log):
|
252
|
-
import json, os, time
|
253
|
-
from filelock import FileLock, Timeout
|
254
|
-
path = os.path.join(os.path.dirname(__file__), '../../../swarm_log.json')
|
255
|
-
lock_path = path + '.lock'
|
256
|
-
log['task_str'] = json.dumps(log['task'])
|
257
|
-
for attempt in range(10):
|
258
|
-
try:
|
259
|
-
with FileLock(lock_path, timeout=5):
|
260
|
-
if os.path.exists(path):
|
261
|
-
with open(path, 'r') as f:
|
262
|
-
try:
|
263
|
-
logs = json.load(f)
|
264
|
-
except json.JSONDecodeError:
|
265
|
-
logs = []
|
266
|
-
else:
|
267
|
-
logs = []
|
268
|
-
logs.append(log)
|
269
|
-
with open(path, 'w') as f:
|
270
|
-
json.dump(logs, f, indent=2)
|
271
|
-
break
|
272
|
-
except Timeout:
|
273
|
-
time.sleep(0.2 * (attempt + 1))
|
274
|
-
|
275
|
-
def create_starting_agent(self, mcp_servers):
|
276
|
-
echo_agent = self.make_agent(
|
277
|
-
name="EchoCraft",
|
278
|
-
instructions="You are EchoCraft, the echo agent. You can use fileops tools (read_file, write_file, list_files, execute_shell_command) for any file or shell tasks.",
|
279
|
-
tools=[self.read_file_tool, self.write_file_tool, self.list_files_tool, self.execute_shell_command_tool],
|
280
|
-
mcp_servers=mcp_servers
|
281
|
-
)
|
282
|
-
return echo_agent
|
283
|
-
|
284
|
-
# --- Spinner and ANSI/emoji operation box for unified UX (for CLI/dev runs) ---
|
285
|
-
from swarm.ux.ansi_box import ansi_box
|
286
|
-
from rich.console import Console
|
287
|
-
from rich.style import Style
|
288
|
-
from rich.text import Text
|
289
|
-
import threading
|
290
|
-
import time
|
291
|
-
|
292
|
-
class EchoCraftSpinner:
|
293
|
-
FRAMES = [
|
294
|
-
"Generating.", "Generating..", "Generating...", "Running...",
|
295
|
-
"⠋ Generating...", "⠙ Generating...", "⠹ Generating...", "⠸ Generating...",
|
296
|
-
"⠼ Generating...", "⠴ Generating...", "⠦ Generating...", "⠧ Generating...",
|
297
|
-
"⠇ Generating...", "⠏ Generating...", "🤖 Generating...", "💡 Generating...", "✨ Generating..."
|
298
|
-
]
|
299
|
-
SLOW_FRAME = "Generating... Taking longer than expected"
|
300
|
-
INTERVAL = 0.12
|
301
|
-
SLOW_THRESHOLD = 10 # seconds
|
302
|
-
|
303
|
-
def __init__(self):
|
304
|
-
self._stop_event = threading.Event()
|
305
|
-
self._thread = None
|
306
|
-
self._start_time = None
|
307
|
-
self.console = Console()
|
308
|
-
self._last_frame = None
|
309
|
-
self._last_slow = False
|
310
|
-
|
311
|
-
def start(self):
|
312
|
-
self._stop_event.clear()
|
313
|
-
self._start_time = time.time()
|
314
|
-
self._thread = threading.Thread(target=self._spin, daemon=True)
|
315
|
-
self._thread.start()
|
316
|
-
|
317
|
-
def _spin(self):
|
318
|
-
idx = 0
|
319
|
-
while not self._stop_event.is_set():
|
320
|
-
elapsed = time.time() - self._start_time
|
321
|
-
if elapsed > self.SLOW_THRESHOLD:
|
322
|
-
txt = Text(self.SLOW_FRAME, style=Style(color="yellow", bold=True))
|
323
|
-
self._last_frame = self.SLOW_FRAME
|
324
|
-
self._last_slow = True
|
325
|
-
else:
|
326
|
-
frame = self.FRAMES[idx % len(self.FRAMES)]
|
327
|
-
txt = Text(frame, style=Style(color="cyan", bold=True))
|
328
|
-
self._last_frame = frame
|
329
|
-
self._last_slow = False
|
330
|
-
self.console.print(txt, end="\r", soft_wrap=True, highlight=False)
|
331
|
-
time.sleep(self.INTERVAL)
|
332
|
-
idx += 1
|
333
|
-
self.console.print(" " * 40, end="\r") # Clear line
|
334
|
-
|
335
|
-
def stop(self, final_message="Done!"):
|
336
|
-
self._stop_event.set()
|
337
|
-
if self._thread:
|
338
|
-
self._thread.join()
|
339
|
-
self.console.print(Text(final_message, style=Style(color="green", bold=True)))
|
340
|
-
|
341
|
-
def current_spinner_state(self):
|
342
|
-
if self._last_slow:
|
343
|
-
return self.SLOW_FRAME
|
344
|
-
return self._last_frame or self.FRAMES[0]
|
345
|
-
|
346
|
-
|
347
|
-
def print_operation_box(op_type, results, params=None, result_type="echo", taking_long=False):
|
348
|
-
emoji = "🗣️" if result_type == "echo" else "🔍"
|
349
|
-
style = 'success' if result_type == "echo" else 'default'
|
350
|
-
box_title = op_type if op_type else ("EchoCraft Output" if result_type == "echo" else "Results")
|
351
|
-
summary_lines = []
|
352
|
-
count = len(results) if isinstance(results, list) else 0
|
353
|
-
summary_lines.append(f"Results: {count}")
|
354
|
-
if params:
|
355
|
-
for k, v in params.items():
|
356
|
-
summary_lines.append(f"{k.capitalize()}: {v}")
|
357
|
-
box_content = "\n".join(summary_lines + ["\n".join(map(str, results))])
|
358
|
-
ansi_box(box_title, box_content, count=count, params=params, style=style if not taking_long else 'warning', emoji=emoji)
|
359
|
-
|
360
|
-
if __name__ == "__main__":
|
361
|
-
import asyncio
|
362
|
-
import json
|
363
|
-
print("\033[1;36m\n╔══════════════════════════════════════════════════════════════╗\n║ 🗣️ ECHOCRAFT: MESSAGE MIRROR & SWARM UX DEMO ║\n╠══════════════════════════════════════════════════════════════╣\n║ This blueprint echoes user messages, demonstrates swarm UX, ║\n║ and showcases viral docstring propagation. ║\n║ Try running: python blueprint_echocraft.py ║\n╚══════════════════════════════════════════════════════════════╝\033[0m")
|
364
|
-
messages = [
|
365
|
-
{"role": "user", "content": "Show me how EchoCraft mirrors messages and benefits from swarm UX patterns."}
|
366
|
-
]
|
367
|
-
blueprint = EchoCraftBlueprint(blueprint_id="demo-1")
|
368
|
-
async def run_and_print():
|
369
|
-
spinner = EchoCraftSpinner()
|
370
|
-
spinner.start()
|
371
|
-
try:
|
372
|
-
all_results = []
|
373
|
-
async for response in blueprint.run(messages):
|
374
|
-
content = response["messages"][0]["content"]
|
375
|
-
all_results.append(content)
|
376
|
-
finally:
|
377
|
-
spinner.stop()
|
378
|
-
print_operation_box(
|
379
|
-
op_type="EchoCraft Output",
|
380
|
-
results=all_results,
|
381
|
-
params={"prompt": messages[0]["content"]},
|
382
|
-
result_type="echo"
|
383
|
-
)
|
384
|
-
asyncio.run(run_and_print())
|
swarm/blueprints/flock/README.md
DELETED
@@ -1,8 +0,0 @@
|
|
1
|
-
# Enhanced search/analysis UX: show ANSI/emoji boxes, summarize results, show result counts, display params, update line numbers, distinguish code/semantic
|
2
|
-
# This is a stub for flock blueprint search/analysis UX. (If this blueprint is implemented, the run method should follow the unified UX pattern.)
|
3
|
-
|
4
|
-
# No run method in __init__.py, but if/when a blueprint is implemented here, ensure:
|
5
|
-
# - Support for both code and semantic search (with clear output distinction)
|
6
|
-
# - ANSI/emoji boxes for search/analysis, with result counts, search params, and progress
|
7
|
-
# - Creative output box for non-search/agent output
|
8
|
-
# - Spinner states: 'Generating.', 'Generating..', 'Generating...', 'Running...'
|
swarm/blueprints/geese/README.md
DELETED
@@ -1,10 +0,0 @@
|
|
1
|
-
# Geese Blueprint
|
2
|
-
|
3
|
-
This is the README stub for the Geese blueprint.
|
4
|
-
|
5
|
-
- **Purpose:** Collaborative agent team for Open Swarm.
|
6
|
-
- **Required Env Vars:** _Document if any._
|
7
|
-
- **Tests:** See `tests/blueprints/test_geese.py` (if exists).
|
8
|
-
- **Usage:** `swarm-cli run geese --instruction "ping"`
|
9
|
-
|
10
|
-
_Expand this README with configuration, usage, and extension details as needed._
|
@@ -1,8 +0,0 @@
|
|
1
|
-
# Enhanced search/analysis UX: show ANSI/emoji boxes, summarize results, show result counts, display params, update line numbers, distinguish code/semantic
|
2
|
-
# This is a stub for geese blueprint search/analysis UX. (If this blueprint is implemented, the run method should follow the unified UX pattern.)
|
3
|
-
|
4
|
-
# No run method in __init__.py, but if/when a blueprint is implemented here, ensure:
|
5
|
-
# - Support for both code and semantic search (with clear output distinction)
|
6
|
-
# - ANSI/emoji boxes for search/analysis, with result counts, search params, and progress
|
7
|
-
# - Creative output box for non-search/agent output
|
8
|
-
# - Spinner states: 'Generating.', 'Generating..', 'Generating...', 'Running...'
|