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,423 +0,0 @@
|
|
1
|
-
"""
|
2
|
-
MissionImprobable Blueprint
|
3
|
-
|
4
|
-
Viral docstring update: Operational as of 2025-04-18T10:14:18Z (UTC).
|
5
|
-
Self-healing, fileops-enabled, swarm-scalable.
|
6
|
-
"""
|
7
|
-
import logging
|
8
|
-
import os
|
9
|
-
import sys
|
10
|
-
import json
|
11
|
-
import sqlite3 # Use standard sqlite3 module
|
12
|
-
from pathlib import Path
|
13
|
-
from typing import Dict, Any, List, ClassVar, Optional
|
14
|
-
from datetime import datetime
|
15
|
-
import pytz
|
16
|
-
|
17
|
-
# Last swarm update: 2025-04-18T10:15:21Z (UTC)
|
18
|
-
|
19
|
-
# Ensure src is in path for BlueprintBase import
|
20
|
-
project_root = os.path.abspath(os.path.join(os.path.dirname(__file__), '..', '..'))
|
21
|
-
src_path = os.path.join(project_root, 'src')
|
22
|
-
if src_path not in sys.path: sys.path.insert(0, src_path)
|
23
|
-
|
24
|
-
try:
|
25
|
-
from agents import Agent, Tool, function_tool, Runner
|
26
|
-
from agents.mcp import MCPServer
|
27
|
-
from agents.models.interface import Model
|
28
|
-
from agents.models.openai_chatcompletions import OpenAIChatCompletionsModel
|
29
|
-
from openai import AsyncOpenAI
|
30
|
-
from swarm.core.blueprint_base import BlueprintBase
|
31
|
-
from swarm.core.blueprint_ux import BlueprintUXImproved
|
32
|
-
except ImportError as e:
|
33
|
-
print(f"ERROR: Import failed in MissionImprobableBlueprint: {e}. Check dependencies.")
|
34
|
-
print(f"sys.path: {sys.path}")
|
35
|
-
sys.exit(1)
|
36
|
-
|
37
|
-
logger = logging.getLogger(__name__)
|
38
|
-
|
39
|
-
# Patch: Expose underlying fileops functions for direct testing
|
40
|
-
class PatchedFunctionTool:
|
41
|
-
def __init__(self, func, name):
|
42
|
-
self.func = func
|
43
|
-
self.name = name
|
44
|
-
|
45
|
-
def read_file(path: str) -> str:
|
46
|
-
try:
|
47
|
-
with open(path, 'r') as f:
|
48
|
-
return f.read()
|
49
|
-
except Exception as e:
|
50
|
-
return f"ERROR: {e}"
|
51
|
-
def write_file(path: str, content: str) -> str:
|
52
|
-
try:
|
53
|
-
with open(path, 'w') as f:
|
54
|
-
f.write(content)
|
55
|
-
return "OK: file written"
|
56
|
-
except Exception as e:
|
57
|
-
return f"ERROR: {e}"
|
58
|
-
def list_files(directory: str = '.') -> str:
|
59
|
-
try:
|
60
|
-
return '\n'.join(os.listdir(directory))
|
61
|
-
except Exception as e:
|
62
|
-
return f"ERROR: {e}"
|
63
|
-
def execute_shell_command(command: str) -> str:
|
64
|
-
"""
|
65
|
-
Executes a shell command and returns its stdout and stderr.
|
66
|
-
Timeout is configurable via SWARM_COMMAND_TIMEOUT (default: 60s).
|
67
|
-
"""
|
68
|
-
logger.info(f"Executing shell command: {command}")
|
69
|
-
try:
|
70
|
-
import os
|
71
|
-
timeout = int(os.getenv("SWARM_COMMAND_TIMEOUT", "60"))
|
72
|
-
result = subprocess.run(command, shell=True, capture_output=True, text=True, timeout=timeout)
|
73
|
-
output = f"Exit Code: {result.returncode}\n"
|
74
|
-
if result.stdout:
|
75
|
-
output += f"STDOUT:\n{result.stdout}\n"
|
76
|
-
if result.stderr:
|
77
|
-
output += f"STDERR:\n{result.stderr}\n"
|
78
|
-
logger.info(f"Command finished. Exit Code: {result.returncode}")
|
79
|
-
return output.strip()
|
80
|
-
except subprocess.TimeoutExpired:
|
81
|
-
logger.error(f"Command timed out: {command}")
|
82
|
-
return f"Error: Command timed out after {os.getenv('SWARM_COMMAND_TIMEOUT', '60')} seconds."
|
83
|
-
except Exception as e:
|
84
|
-
logger.error(f"Error executing command '{command}': {e}", exc_info=True)
|
85
|
-
return f"Error executing command: {e}"
|
86
|
-
read_file_tool = PatchedFunctionTool(read_file, 'read_file')
|
87
|
-
write_file_tool = PatchedFunctionTool(write_file, 'write_file')
|
88
|
-
list_files_tool = PatchedFunctionTool(list_files, 'list_files')
|
89
|
-
execute_shell_command_tool = PatchedFunctionTool(execute_shell_command, 'execute_shell_command')
|
90
|
-
|
91
|
-
# --- Database Constants ---
|
92
|
-
# Using the same DB file as dilbot_universe
|
93
|
-
DB_FILE_NAME = "swarm_instructions.db"
|
94
|
-
DB_PATH = Path(project_root) / DB_FILE_NAME
|
95
|
-
TABLE_NAME = "agent_instructions" # agent_name TEXT PRIMARY KEY, instruction_text TEXT, model_profile TEXT
|
96
|
-
|
97
|
-
# Spinner UX enhancement (Open Swarm TODO)
|
98
|
-
SPINNER_STATES = ['Generating.', 'Generating..', 'Generating...', 'Running...']
|
99
|
-
|
100
|
-
# --- Define the Blueprint ---
|
101
|
-
# Renamed class for consistency
|
102
|
-
class MissionImprobableBlueprint(BlueprintBase):
|
103
|
-
"""A cheeky team on a mission: led by JimFlimsy with support from CinnamonToast and RollinFumble."""
|
104
|
-
metadata: ClassVar[Dict[str, Any]] = {
|
105
|
-
"name": "MissionImprobableBlueprint",
|
106
|
-
"title": "Mission: Improbable",
|
107
|
-
"description": "A cheeky team led by JimFlimsy (coordinator), CinnamonToast (strategist/filesystem), and RollinFumble (operative/shell). Uses SQLite for instructions.",
|
108
|
-
"version": "1.1.0", # Refactored version
|
109
|
-
"author": "Open Swarm Team (Refactored)",
|
110
|
-
"tags": ["comedy", "multi-agent", "filesystem", "shell", "sqlite"],
|
111
|
-
"required_mcp_servers": ["memory", "filesystem", "mcp-shell"], # Servers needed by the agents
|
112
|
-
"env_vars": ["ALLOWED_PATH"], # Informational: filesystem MCP likely needs this
|
113
|
-
}
|
114
|
-
|
115
|
-
# Caches
|
116
|
-
_openai_client_cache: Dict[str, AsyncOpenAI] = {}
|
117
|
-
_model_instance_cache: Dict[str, Model] = {}
|
118
|
-
_db_initialized = False # Flag to ensure DB init runs only once per instance
|
119
|
-
|
120
|
-
def __init__(self, blueprint_id: str = "mission_improbable", config=None, config_path=None, **kwargs):
|
121
|
-
super().__init__(blueprint_id, config=config, config_path=config_path, **kwargs)
|
122
|
-
self.blueprint_id = blueprint_id
|
123
|
-
self.config_path = config_path
|
124
|
-
self._config = config if config is not None else None
|
125
|
-
self._llm_profile_name = None
|
126
|
-
self._llm_profile_data = None
|
127
|
-
self._markdown_output = None
|
128
|
-
# Add other attributes as needed for MissionImprobable
|
129
|
-
# ...
|
130
|
-
|
131
|
-
# --- Database Interaction ---
|
132
|
-
def _init_db_and_load_data(self) -> None:
|
133
|
-
"""Initializes the SQLite DB, creates table, and loads sample data if needed."""
|
134
|
-
"""Initializes the SQLite DB file and loads sample instruction for JimFlimsy."""
|
135
|
-
if self._db_initialized:
|
136
|
-
return
|
137
|
-
# Create parent directory if needed
|
138
|
-
try:
|
139
|
-
DB_PATH.parent.mkdir(parents=True, exist_ok=True)
|
140
|
-
# Create or open the database file
|
141
|
-
with open(DB_PATH, 'a'):
|
142
|
-
pass
|
143
|
-
# Initialize DB and table
|
144
|
-
conn = sqlite3.connect(str(DB_PATH))
|
145
|
-
cursor = conn.cursor()
|
146
|
-
cursor.execute(f"CREATE TABLE IF NOT EXISTS {TABLE_NAME} (agent_name TEXT PRIMARY KEY, instruction_text TEXT NOT NULL, model_profile TEXT DEFAULT 'default')")
|
147
|
-
# Load sample data for JimFlimsy if not present
|
148
|
-
cursor.execute("SELECT COUNT(*) FROM " + TABLE_NAME + " WHERE agent_name = ?", ("JimFlimsy",))
|
149
|
-
count = cursor.fetchone()[0]
|
150
|
-
if count == 0:
|
151
|
-
cursor.execute(
|
152
|
-
"INSERT OR IGNORE INTO " + TABLE_NAME + " (agent_name, instruction_text, model_profile) VALUES (?, ?, ?)",
|
153
|
-
("JimFlimsy", "You’re JimFlimsy, the fearless leader.", "default")
|
154
|
-
)
|
155
|
-
conn.commit()
|
156
|
-
conn.close()
|
157
|
-
self._db_initialized = True
|
158
|
-
except Exception as e:
|
159
|
-
logger.error(f"Error during DB initialization/loading: {e}", exc_info=True)
|
160
|
-
self._db_initialized = False
|
161
|
-
|
162
|
-
def get_agent_config(self, agent_name: str) -> Dict[str, Any]:
|
163
|
-
"""Fetches agent config from SQLite DB or returns defaults."""
|
164
|
-
if self._db_initialized:
|
165
|
-
try:
|
166
|
-
with sqlite3.connect(DB_PATH) as conn:
|
167
|
-
conn.row_factory = sqlite3.Row
|
168
|
-
cursor = conn.cursor()
|
169
|
-
cursor.execute(f"SELECT instruction_text, model_profile FROM {TABLE_NAME} WHERE agent_name = ?", (agent_name,))
|
170
|
-
row = cursor.fetchone()
|
171
|
-
if row:
|
172
|
-
logger.debug(f"Loaded config for agent '{agent_name}' from SQLite.")
|
173
|
-
return {"instructions": row["instruction_text"], "model_profile": row["model_profile"] or "default"}
|
174
|
-
else:
|
175
|
-
logger.warning(f"No config found for agent '{agent_name}' in SQLite. Using defaults.")
|
176
|
-
except sqlite3.Error as e:
|
177
|
-
logger.error(f"SQLite error fetching config for '{agent_name}': {e}. Using defaults.", exc_info=True)
|
178
|
-
except Exception as e:
|
179
|
-
logger.error(f"Unexpected error fetching config for '{agent_name}': {e}. Using defaults.", exc_info=True)
|
180
|
-
|
181
|
-
# --- Fallback Hardcoded Defaults ---
|
182
|
-
logger.warning(f"Using hardcoded default config for agent '{agent_name}'.")
|
183
|
-
default_instructions = {
|
184
|
-
"JimFlimsy": "You are JimFlimsy, the leader. Delegate tasks. [Default - DB Failed]",
|
185
|
-
"CinnamonToast": "You are CinnamonToast, strategist. Use filesystem. [Default - DB Failed]",
|
186
|
-
"RollinFumble": "You are RollinFumble, operative. Use shell. [Default - DB Failed]",
|
187
|
-
}
|
188
|
-
return {
|
189
|
-
"instructions": default_instructions.get(agent_name, f"Default instructions for {agent_name}."),
|
190
|
-
"model_profile": "default",
|
191
|
-
}
|
192
|
-
|
193
|
-
# --- Model Instantiation Helper --- (Standard helper)
|
194
|
-
def _get_model_instance(self, profile_name: str) -> Model:
|
195
|
-
"""Retrieves or creates an LLM Model instance."""
|
196
|
-
# ... (Implementation is the same as previous refactors) ...
|
197
|
-
if profile_name in self._model_instance_cache:
|
198
|
-
logger.debug(f"Using cached Model instance for profile '{profile_name}'.")
|
199
|
-
return self._model_instance_cache[profile_name]
|
200
|
-
logger.debug(f"Creating new Model instance for profile '{profile_name}'.")
|
201
|
-
profile_data = self.get_llm_profile(profile_name)
|
202
|
-
if not profile_data:
|
203
|
-
logger.critical(f"LLM profile '{profile_name}' (or 'default') not found.")
|
204
|
-
raise ValueError(f"Missing LLM profile configuration for '{profile_name}' or 'default'.")
|
205
|
-
provider = profile_data.get("provider", "openai").lower()
|
206
|
-
model_name = profile_data.get("model")
|
207
|
-
if not model_name:
|
208
|
-
logger.critical(f"LLM profile '{profile_name}' missing 'model' key.")
|
209
|
-
raise ValueError(f"Missing 'model' key in LLM profile '{profile_name}'.")
|
210
|
-
if provider != "openai":
|
211
|
-
logger.error(f"Unsupported LLM provider '{provider}'.")
|
212
|
-
raise ValueError(f"Unsupported LLM provider: {provider}")
|
213
|
-
client_cache_key = f"{provider}_{profile_data.get('base_url')}"
|
214
|
-
if client_cache_key not in self._openai_client_cache:
|
215
|
-
client_kwargs = { "api_key": profile_data.get("api_key"), "base_url": profile_data.get("base_url") }
|
216
|
-
filtered_kwargs = {k: v for k, v in client_kwargs.items() if v is not None}
|
217
|
-
log_kwargs = {k:v for k,v in filtered_kwargs.items() if k != 'api_key'}
|
218
|
-
logger.debug(f"Creating new AsyncOpenAI client for '{profile_name}': {log_kwargs}")
|
219
|
-
try: self._openai_client_cache[client_cache_key] = AsyncOpenAI(**filtered_kwargs)
|
220
|
-
except Exception as e: raise ValueError(f"Failed to init OpenAI client: {e}") from e
|
221
|
-
client = self._openai_client_cache[client_cache_key]
|
222
|
-
logger.debug(f"Instantiating OpenAIChatCompletionsModel(model='{model_name}') for '{profile_name}'.")
|
223
|
-
try:
|
224
|
-
model_instance = OpenAIChatCompletionsModel(model=model_name, openai_client=client)
|
225
|
-
self._model_instance_cache[profile_name] = model_instance
|
226
|
-
return model_instance
|
227
|
-
except Exception as e: raise ValueError(f"Failed to init LLM provider: {e}") from e
|
228
|
-
|
229
|
-
# --- Agent Creation ---
|
230
|
-
def create_starting_agent(self, mcp_servers: List[MCPServer]) -> Agent:
|
231
|
-
"""Creates the Mission Improbable agent team and returns JimFlimsy (Coordinator)."""
|
232
|
-
# Initialize DB and load data if needed
|
233
|
-
self._init_db_and_load_data()
|
234
|
-
|
235
|
-
logger.debug("Creating Mission Improbable agent team...")
|
236
|
-
self._model_instance_cache = {}
|
237
|
-
self._openai_client_cache = {}
|
238
|
-
|
239
|
-
# Helper to filter MCP servers
|
240
|
-
def get_agent_mcps(names: List[str]) -> List[MCPServer]:
|
241
|
-
return [s for s in mcp_servers if s.name in names]
|
242
|
-
|
243
|
-
# Create agents, fetching config and assigning MCPs
|
244
|
-
agents: Dict[str, Agent] = {}
|
245
|
-
for name in ["JimFlimsy", "CinnamonToast", "RollinFumble"]:
|
246
|
-
config = self.get_agent_config(name)
|
247
|
-
model_instance = self._get_model_instance(config["model_profile"])
|
248
|
-
agent_mcps = []
|
249
|
-
if name == "JimFlimsy": agent_mcps = get_agent_mcps(["memory"])
|
250
|
-
elif name == "CinnamonToast": agent_mcps = get_agent_mcps(["filesystem"])
|
251
|
-
elif name == "RollinFumble": agent_mcps = get_agent_mcps(["mcp-shell"])
|
252
|
-
|
253
|
-
agents[name] = Agent(
|
254
|
-
name=name,
|
255
|
-
instructions=config["instructions"] + "\nYou can use fileops tools (read_file, write_file, list_files, execute_shell_command) for any file or shell tasks.",
|
256
|
-
model=model_instance,
|
257
|
-
tools=[read_file_tool, write_file_tool, list_files_tool, execute_shell_command_tool],
|
258
|
-
mcp_servers=agent_mcps
|
259
|
-
)
|
260
|
-
|
261
|
-
# Add agent tools to the coordinator (JimFlimsy)
|
262
|
-
agents["JimFlimsy"].tools.extend([
|
263
|
-
agents["CinnamonToast"].as_tool(tool_name="CinnamonToast", tool_description="Delegate file management or strategic planning tasks."),
|
264
|
-
agents["RollinFumble"].as_tool(tool_name="RollinFumble", tool_description="Delegate shell command execution tasks.")
|
265
|
-
])
|
266
|
-
|
267
|
-
logger.debug("Mission Improbable agents created. Starting with JimFlimsy.")
|
268
|
-
return agents["JimFlimsy"] # Jim is the coordinator
|
269
|
-
|
270
|
-
async def run(self, messages: list, **kwargs):
|
271
|
-
"""Main execution entry point for the MissionImprobable blueprint."""
|
272
|
-
logger.info("MissionImprobableBlueprint run method called.")
|
273
|
-
instruction = messages[-1].get("content", "") if messages else ""
|
274
|
-
from agents import Runner
|
275
|
-
ux = BlueprintUXImproved(style="serious")
|
276
|
-
spinner_idx = 0
|
277
|
-
start_time = time.time()
|
278
|
-
spinner_yield_interval = 1.0 # seconds
|
279
|
-
last_spinner_time = start_time
|
280
|
-
yielded_spinner = False
|
281
|
-
result_chunks = []
|
282
|
-
try:
|
283
|
-
runner_gen = Runner.run(self.create_starting_agent([]), instruction)
|
284
|
-
while True:
|
285
|
-
now = time.time()
|
286
|
-
try:
|
287
|
-
chunk = next(runner_gen)
|
288
|
-
result_chunks.append(chunk)
|
289
|
-
# If chunk is a final result, wrap and yield
|
290
|
-
if chunk and isinstance(chunk, dict) and "messages" in chunk:
|
291
|
-
content = chunk["messages"][0]["content"] if chunk["messages"] else ""
|
292
|
-
summary = ux.summary("Operation", len(result_chunks), {"instruction": instruction[:40]})
|
293
|
-
box = ux.ansi_emoji_box(
|
294
|
-
title="MissionImprobable Result",
|
295
|
-
content=content,
|
296
|
-
summary=summary,
|
297
|
-
params={"instruction": instruction[:40]},
|
298
|
-
result_count=len(result_chunks),
|
299
|
-
op_type="run",
|
300
|
-
status="success"
|
301
|
-
)
|
302
|
-
yield {"messages": [{"role": "assistant", "content": box}]}
|
303
|
-
else:
|
304
|
-
yield chunk
|
305
|
-
yielded_spinner = False
|
306
|
-
except StopIteration:
|
307
|
-
break
|
308
|
-
except Exception:
|
309
|
-
if now - last_spinner_time >= spinner_yield_interval:
|
310
|
-
taking_long = (now - start_time > 10)
|
311
|
-
spinner_msg = ux.spinner(spinner_idx, taking_long=taking_long)
|
312
|
-
yield {"messages": [{"role": "assistant", "content": spinner_msg}]}
|
313
|
-
spinner_idx += 1
|
314
|
-
last_spinner_time = now
|
315
|
-
yielded_spinner = True
|
316
|
-
if not result_chunks and not yielded_spinner:
|
317
|
-
yield {"messages": [{"role": "assistant", "content": ux.spinner(0)}]}
|
318
|
-
except Exception as e:
|
319
|
-
logger.error(f"Error during MissionImprobable run: {e}", exc_info=True)
|
320
|
-
yield {"messages": [{"role": "assistant", "content": f"An error occurred: {e}"}]}
|
321
|
-
|
322
|
-
# --- Spinner and ANSI/emoji operation box for unified UX (for CLI/dev runs) ---
|
323
|
-
from swarm.ux.ansi_box import ansi_box
|
324
|
-
from rich.console import Console
|
325
|
-
from rich.style import Style
|
326
|
-
from rich.text import Text
|
327
|
-
import threading
|
328
|
-
import time
|
329
|
-
|
330
|
-
class MissionImprobableSpinner:
|
331
|
-
FRAMES = [
|
332
|
-
"Generating.", "Generating..", "Generating...", "Running...",
|
333
|
-
"⠋ Generating...", "⠙ Generating...", "⠹ Generating...", "⠸ Generating...",
|
334
|
-
"⠼ Generating...", "⠴ Generating...", "⠦ Generating...", "⠧ Generating...",
|
335
|
-
"⠇ Generating...", "⠏ Generating...", "🤖 Generating...", "💡 Generating...", "✨ Generating..."
|
336
|
-
]
|
337
|
-
SLOW_FRAME = "Generating... Taking longer than expected"
|
338
|
-
INTERVAL = 0.12
|
339
|
-
SLOW_THRESHOLD = 10 # seconds
|
340
|
-
|
341
|
-
def __init__(self):
|
342
|
-
self._stop_event = threading.Event()
|
343
|
-
self._thread = None
|
344
|
-
self._start_time = None
|
345
|
-
self.console = Console()
|
346
|
-
self._last_frame = None
|
347
|
-
self._last_slow = False
|
348
|
-
|
349
|
-
def start(self):
|
350
|
-
self._stop_event.clear()
|
351
|
-
self._start_time = time.time()
|
352
|
-
self._thread = threading.Thread(target=self._spin, daemon=True)
|
353
|
-
self._thread.start()
|
354
|
-
|
355
|
-
def _spin(self):
|
356
|
-
idx = 0
|
357
|
-
while not self._stop_event.is_set():
|
358
|
-
elapsed = time.time() - self._start_time
|
359
|
-
if elapsed > self.SLOW_THRESHOLD:
|
360
|
-
txt = Text(self.SLOW_FRAME, style=Style(color="yellow", bold=True))
|
361
|
-
self._last_frame = self.SLOW_FRAME
|
362
|
-
self._last_slow = True
|
363
|
-
else:
|
364
|
-
frame = self.FRAMES[idx % len(self.FRAMES)]
|
365
|
-
txt = Text(frame, style=Style(color="cyan", bold=True))
|
366
|
-
self._last_frame = frame
|
367
|
-
self._last_slow = False
|
368
|
-
self.console.print(txt, end="\r", soft_wrap=True, highlight=False)
|
369
|
-
time.sleep(self.INTERVAL)
|
370
|
-
idx += 1
|
371
|
-
self.console.print(" " * 40, end="\r") # Clear line
|
372
|
-
|
373
|
-
def stop(self, final_message="Done!"):
|
374
|
-
self._stop_event.set()
|
375
|
-
if self._thread:
|
376
|
-
self._thread.join()
|
377
|
-
self.console.print(Text(final_message, style=Style(color="green", bold=True)))
|
378
|
-
|
379
|
-
def current_spinner_state(self):
|
380
|
-
if self._last_slow:
|
381
|
-
return self.SLOW_FRAME
|
382
|
-
return self._last_frame or self.FRAMES[0]
|
383
|
-
|
384
|
-
|
385
|
-
def print_operation_box(op_type, results, params=None, result_type="mission", taking_long=False):
|
386
|
-
emoji = "🕵️" if result_type == "mission" else "🔍"
|
387
|
-
style = 'success' if result_type == "mission" else 'default'
|
388
|
-
box_title = op_type if op_type else ("MissionImprobable Output" if result_type == "mission" else "Results")
|
389
|
-
summary_lines = []
|
390
|
-
count = len(results) if isinstance(results, list) else 0
|
391
|
-
summary_lines.append(f"Results: {count}")
|
392
|
-
if params:
|
393
|
-
for k, v in params.items():
|
394
|
-
summary_lines.append(f"{k.capitalize()}: {v}")
|
395
|
-
box_content = "\n".join(summary_lines + ["\n".join(map(str, results))])
|
396
|
-
ansi_box(box_title, box_content, count=count, params=params, style=style if not taking_long else 'warning', emoji=emoji)
|
397
|
-
|
398
|
-
# Standard Python entry point
|
399
|
-
if __name__ == "__main__":
|
400
|
-
import asyncio
|
401
|
-
import json
|
402
|
-
print("\033[1;36m\n╔══════════════════════════════════════════════════════════════╗\n║ 🕵️ MISSION IMPROBABLE: SWARM STRATEGY & TASK DEMO ║\n╠══════════════════════════════════════════════════════════════╣\n║ This blueprint demonstrates viral swarm propagation, ║\n║ strategic task planning, and agent collaboration. ║\n║ Try running: python blueprint_mission_improbable.py ║\n╚══════════════════════════════════════════════════════════════╝\033[0m")
|
403
|
-
messages = [
|
404
|
-
{"role": "user", "content": "Show me how Mission Improbable plans tasks and leverages swarm strategy."}
|
405
|
-
]
|
406
|
-
blueprint = MissionImprobableBlueprint(blueprint_id="demo-1")
|
407
|
-
async def run_and_print():
|
408
|
-
spinner = MissionImprobableSpinner()
|
409
|
-
spinner.start()
|
410
|
-
try:
|
411
|
-
all_results = []
|
412
|
-
async for response in blueprint.run(messages):
|
413
|
-
content = response["messages"][0]["content"]
|
414
|
-
all_results.append(content)
|
415
|
-
finally:
|
416
|
-
spinner.stop()
|
417
|
-
print_operation_box(
|
418
|
-
op_type="MissionImprobable Output",
|
419
|
-
results=all_results,
|
420
|
-
params={"prompt": messages[0]["content"]},
|
421
|
-
result_type="mission"
|
422
|
-
)
|
423
|
-
asyncio.run(run_and_print())
|