open-swarm 0.1.1745274976__py3-none-any.whl → 0.1.1748636259__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- open_swarm-0.1.1748636259.dist-info/METADATA +188 -0
- open_swarm-0.1.1748636259.dist-info/RECORD +82 -0
- {open_swarm-0.1.1745274976.dist-info → open_swarm-0.1.1748636259.dist-info}/WHEEL +2 -1
- open_swarm-0.1.1748636259.dist-info/entry_points.txt +3 -0
- open_swarm-0.1.1748636259.dist-info/top_level.txt +1 -0
- swarm/agent/agent.py +49 -0
- swarm/auth.py +48 -113
- swarm/consumers.py +0 -19
- swarm/extensions/blueprint/__init__.py +16 -30
- swarm/{core → extensions/blueprint}/agent_utils.py +1 -1
- swarm/extensions/blueprint/blueprint_base.py +458 -0
- swarm/extensions/blueprint/blueprint_discovery.py +112 -0
- swarm/extensions/blueprint/output_utils.py +95 -0
- swarm/{core → extensions/blueprint}/spinner.py +21 -30
- swarm/extensions/cli/cli_args.py +0 -6
- swarm/extensions/cli/commands/blueprint_management.py +9 -47
- swarm/extensions/cli/commands/config_management.py +6 -5
- swarm/extensions/cli/commands/edit_config.py +7 -16
- swarm/extensions/cli/commands/list_blueprints.py +1 -1
- swarm/extensions/cli/commands/validate_env.py +4 -11
- swarm/extensions/cli/commands/validate_envvars.py +6 -6
- swarm/extensions/cli/interactive_shell.py +2 -16
- swarm/extensions/config/config_loader.py +201 -107
- swarm/{core → extensions/config}/config_manager.py +38 -50
- swarm/{core → extensions/config}/server_config.py +0 -32
- swarm/extensions/launchers/build_launchers.py +14 -0
- swarm/{core → extensions/launchers}/build_swarm_wrapper.py +0 -0
- swarm/extensions/launchers/swarm_api.py +64 -8
- swarm/extensions/launchers/swarm_cli.py +300 -8
- swarm/llm/chat_completion.py +195 -0
- swarm/serializers.py +5 -96
- swarm/settings.py +111 -99
- swarm/urls.py +74 -57
- swarm/utils/context_utils.py +4 -10
- swarm/utils/general_utils.py +0 -21
- swarm/utils/redact.py +36 -23
- swarm/views/api_views.py +39 -48
- swarm/views/chat_views.py +70 -237
- swarm/views/core_views.py +87 -80
- swarm/views/model_views.py +121 -64
- swarm/views/utils.py +441 -65
- swarm/views/web_views.py +2 -2
- open_swarm-0.1.1745274976.dist-info/METADATA +0 -874
- open_swarm-0.1.1745274976.dist-info/RECORD +0 -318
- open_swarm-0.1.1745274976.dist-info/entry_points.txt +0 -4
- swarm/blueprints/README.md +0 -68
- swarm/blueprints/blueprint_audit_status.json +0 -27
- swarm/blueprints/chatbot/README.md +0 -40
- swarm/blueprints/chatbot/blueprint_chatbot.py +0 -471
- swarm/blueprints/chatbot/metadata.json +0 -23
- swarm/blueprints/chatbot/templates/chatbot/chatbot.html +0 -33
- swarm/blueprints/chucks_angels/README.md +0 -11
- swarm/blueprints/chucks_angels/blueprint_chucks_angels.py +0 -7
- swarm/blueprints/chucks_angels/test_basic.py +0 -3
- swarm/blueprints/codey/CODEY.md +0 -15
- swarm/blueprints/codey/README.md +0 -115
- swarm/blueprints/codey/blueprint_codey.py +0 -1072
- swarm/blueprints/codey/codey_cli.py +0 -373
- swarm/blueprints/codey/instructions.md +0 -17
- swarm/blueprints/codey/metadata.json +0 -23
- swarm/blueprints/common/operation_box_utils.py +0 -83
- swarm/blueprints/digitalbutlers/README.md +0 -11
- swarm/blueprints/digitalbutlers/__init__.py +0 -1
- swarm/blueprints/digitalbutlers/blueprint_digitalbutlers.py +0 -7
- swarm/blueprints/digitalbutlers/test_basic.py +0 -3
- swarm/blueprints/divine_code/README.md +0 -3
- swarm/blueprints/divine_code/__init__.py +0 -10
- swarm/blueprints/divine_code/apps.py +0 -11
- swarm/blueprints/divine_code/blueprint_divine_code.py +0 -270
- swarm/blueprints/django_chat/apps.py +0 -6
- swarm/blueprints/django_chat/blueprint_django_chat.py +0 -268
- swarm/blueprints/django_chat/templates/django_chat/django_chat_webpage.html +0 -37
- swarm/blueprints/django_chat/urls.py +0 -8
- swarm/blueprints/django_chat/views.py +0 -32
- swarm/blueprints/echocraft/blueprint_echocraft.py +0 -384
- swarm/blueprints/flock/README.md +0 -11
- swarm/blueprints/flock/__init__.py +0 -8
- swarm/blueprints/flock/blueprint_flock.py +0 -7
- swarm/blueprints/flock/test_basic.py +0 -3
- swarm/blueprints/geese/README.md +0 -97
- swarm/blueprints/geese/blueprint_geese.py +0 -803
- swarm/blueprints/geese/geese_cli.py +0 -102
- swarm/blueprints/jeeves/README.md +0 -41
- swarm/blueprints/jeeves/blueprint_jeeves.py +0 -722
- swarm/blueprints/jeeves/jeeves_cli.py +0 -55
- swarm/blueprints/jeeves/metadata.json +0 -24
- swarm/blueprints/mcp_demo/blueprint_mcp_demo.py +0 -473
- swarm/blueprints/messenger/templates/messenger/messenger.html +0 -46
- swarm/blueprints/mission_improbable/blueprint_mission_improbable.py +0 -423
- swarm/blueprints/monkai_magic/blueprint_monkai_magic.py +0 -340
- swarm/blueprints/nebula_shellz/blueprint_nebula_shellz.py +0 -265
- swarm/blueprints/omniplex/blueprint_omniplex.py +0 -298
- swarm/blueprints/poets/blueprint_poets.py +0 -546
- swarm/blueprints/poets/poets_cli.py +0 -23
- swarm/blueprints/rue_code/README.md +0 -8
- swarm/blueprints/rue_code/blueprint_rue_code.py +0 -448
- swarm/blueprints/rue_code/rue_code_cli.py +0 -43
- swarm/blueprints/stewie/apps.py +0 -12
- swarm/blueprints/stewie/blueprint_family_ties.py +0 -349
- swarm/blueprints/stewie/models.py +0 -19
- swarm/blueprints/stewie/serializers.py +0 -10
- swarm/blueprints/stewie/settings.py +0 -17
- swarm/blueprints/stewie/urls.py +0 -11
- swarm/blueprints/stewie/views.py +0 -26
- swarm/blueprints/suggestion/blueprint_suggestion.py +0 -222
- swarm/blueprints/whinge_surf/README.md +0 -22
- swarm/blueprints/whinge_surf/__init__.py +0 -1
- swarm/blueprints/whinge_surf/blueprint_whinge_surf.py +0 -565
- swarm/blueprints/whinge_surf/whinge_surf_cli.py +0 -99
- swarm/blueprints/whiskeytango_foxtrot/__init__.py +0 -0
- swarm/blueprints/whiskeytango_foxtrot/apps.py +0 -11
- swarm/blueprints/whiskeytango_foxtrot/blueprint_whiskeytango_foxtrot.py +0 -339
- swarm/blueprints/zeus/__init__.py +0 -2
- swarm/blueprints/zeus/apps.py +0 -4
- swarm/blueprints/zeus/blueprint_zeus.py +0 -270
- swarm/blueprints/zeus/zeus_cli.py +0 -13
- swarm/cli/async_input.py +0 -65
- swarm/cli/async_input_demo.py +0 -32
- swarm/core/blueprint_base.py +0 -769
- swarm/core/blueprint_discovery.py +0 -125
- swarm/core/blueprint_runner.py +0 -59
- swarm/core/blueprint_ux.py +0 -109
- swarm/core/build_launchers.py +0 -15
- swarm/core/cli/__init__.py +0 -1
- swarm/core/cli/commands/__init__.py +0 -1
- swarm/core/cli/commands/blueprint_management.py +0 -7
- swarm/core/cli/interactive_shell.py +0 -14
- swarm/core/cli/main.py +0 -50
- swarm/core/cli/utils/__init__.py +0 -1
- swarm/core/cli/utils/discover_commands.py +0 -18
- swarm/core/config_loader.py +0 -122
- swarm/core/output_utils.py +0 -193
- swarm/core/session_logger.py +0 -42
- swarm/core/slash_commands.py +0 -89
- swarm/core/swarm_api.py +0 -68
- swarm/core/swarm_cli.py +0 -216
- swarm/core/utils/__init__.py +0 -0
- swarm/extensions/blueprint/cli_handler.py +0 -197
- swarm/extensions/blueprint/runnable_blueprint.py +0 -42
- swarm/extensions/cli/utils/__init__.py +0 -1
- swarm/extensions/cli/utils/async_input.py +0 -46
- swarm/extensions/cli/utils/prompt_user.py +0 -3
- swarm/management/__init__.py +0 -0
- swarm/management/commands/__init__.py +0 -0
- swarm/management/commands/runserver.py +0 -58
- swarm/middleware.py +0 -65
- swarm/permissions.py +0 -38
- swarm/static/contrib/fonts/fontawesome-webfont.ttf +0 -7
- swarm/static/contrib/fonts/fontawesome-webfont.woff +0 -7
- swarm/static/contrib/fonts/fontawesome-webfont.woff2 +0 -7
- swarm/static/contrib/markedjs/marked.min.js +0 -6
- swarm/static/contrib/tabler-icons/adjustments-horizontal.svg +0 -27
- swarm/static/contrib/tabler-icons/alert-triangle.svg +0 -21
- swarm/static/contrib/tabler-icons/archive.svg +0 -21
- swarm/static/contrib/tabler-icons/artboard.svg +0 -27
- swarm/static/contrib/tabler-icons/automatic-gearbox.svg +0 -23
- swarm/static/contrib/tabler-icons/box-multiple.svg +0 -19
- swarm/static/contrib/tabler-icons/carambola.svg +0 -19
- swarm/static/contrib/tabler-icons/copy.svg +0 -20
- swarm/static/contrib/tabler-icons/download.svg +0 -21
- swarm/static/contrib/tabler-icons/edit.svg +0 -21
- swarm/static/contrib/tabler-icons/filled/carambola.svg +0 -13
- swarm/static/contrib/tabler-icons/filled/paint.svg +0 -13
- swarm/static/contrib/tabler-icons/headset.svg +0 -22
- swarm/static/contrib/tabler-icons/layout-sidebar-left-collapse.svg +0 -21
- swarm/static/contrib/tabler-icons/layout-sidebar-left-expand.svg +0 -21
- swarm/static/contrib/tabler-icons/layout-sidebar-right-collapse.svg +0 -21
- swarm/static/contrib/tabler-icons/layout-sidebar-right-expand.svg +0 -21
- swarm/static/contrib/tabler-icons/message-chatbot.svg +0 -22
- swarm/static/contrib/tabler-icons/message-star.svg +0 -22
- swarm/static/contrib/tabler-icons/message-x.svg +0 -23
- swarm/static/contrib/tabler-icons/message.svg +0 -21
- swarm/static/contrib/tabler-icons/paperclip.svg +0 -18
- swarm/static/contrib/tabler-icons/playlist-add.svg +0 -22
- swarm/static/contrib/tabler-icons/robot.svg +0 -26
- swarm/static/contrib/tabler-icons/search.svg +0 -19
- swarm/static/contrib/tabler-icons/settings.svg +0 -20
- swarm/static/contrib/tabler-icons/thumb-down.svg +0 -19
- swarm/static/contrib/tabler-icons/thumb-up.svg +0 -19
- swarm/static/css/dropdown.css +0 -22
- swarm/static/htmx/htmx.min.js +0 -0
- swarm/static/js/dropdown.js +0 -23
- swarm/static/rest_mode/css/base.css +0 -470
- swarm/static/rest_mode/css/chat-history.css +0 -286
- swarm/static/rest_mode/css/chat.css +0 -251
- swarm/static/rest_mode/css/chatbot.css +0 -74
- swarm/static/rest_mode/css/chatgpt.css +0 -62
- swarm/static/rest_mode/css/colors/corporate.css +0 -74
- swarm/static/rest_mode/css/colors/pastel.css +0 -81
- swarm/static/rest_mode/css/colors/tropical.css +0 -82
- swarm/static/rest_mode/css/general.css +0 -142
- swarm/static/rest_mode/css/layout.css +0 -167
- swarm/static/rest_mode/css/layouts/messenger-layout.css +0 -17
- swarm/static/rest_mode/css/layouts/minimalist-layout.css +0 -57
- swarm/static/rest_mode/css/layouts/mobile-layout.css +0 -8
- swarm/static/rest_mode/css/messages.css +0 -84
- swarm/static/rest_mode/css/messenger.css +0 -135
- swarm/static/rest_mode/css/settings.css +0 -91
- swarm/static/rest_mode/css/simple.css +0 -44
- swarm/static/rest_mode/css/slack.css +0 -58
- swarm/static/rest_mode/css/style.css +0 -156
- swarm/static/rest_mode/css/theme.css +0 -30
- swarm/static/rest_mode/css/toast.css +0 -40
- swarm/static/rest_mode/js/auth.js +0 -9
- swarm/static/rest_mode/js/blueprint.js +0 -41
- swarm/static/rest_mode/js/blueprintUtils.js +0 -12
- swarm/static/rest_mode/js/chatLogic.js +0 -79
- swarm/static/rest_mode/js/debug.js +0 -63
- swarm/static/rest_mode/js/events.js +0 -98
- swarm/static/rest_mode/js/main.js +0 -19
- swarm/static/rest_mode/js/messages.js +0 -264
- swarm/static/rest_mode/js/messengerLogic.js +0 -355
- swarm/static/rest_mode/js/modules/apiService.js +0 -84
- swarm/static/rest_mode/js/modules/blueprintManager.js +0 -162
- swarm/static/rest_mode/js/modules/chatHistory.js +0 -110
- swarm/static/rest_mode/js/modules/debugLogger.js +0 -14
- swarm/static/rest_mode/js/modules/eventHandlers.js +0 -107
- swarm/static/rest_mode/js/modules/messageProcessor.js +0 -120
- swarm/static/rest_mode/js/modules/state.js +0 -7
- swarm/static/rest_mode/js/modules/userInteractions.js +0 -29
- swarm/static/rest_mode/js/modules/validation.js +0 -23
- swarm/static/rest_mode/js/rendering.js +0 -119
- swarm/static/rest_mode/js/settings.js +0 -130
- swarm/static/rest_mode/js/sidebar.js +0 -94
- swarm/static/rest_mode/js/simpleLogic.js +0 -37
- swarm/static/rest_mode/js/slackLogic.js +0 -66
- swarm/static/rest_mode/js/splash.js +0 -76
- swarm/static/rest_mode/js/theme.js +0 -111
- swarm/static/rest_mode/js/toast.js +0 -36
- swarm/static/rest_mode/js/ui.js +0 -265
- swarm/static/rest_mode/js/validation.js +0 -57
- swarm/static/rest_mode/svg/animated_spinner.svg +0 -12
- swarm/static/rest_mode/svg/arrow_down.svg +0 -5
- swarm/static/rest_mode/svg/arrow_left.svg +0 -5
- swarm/static/rest_mode/svg/arrow_right.svg +0 -5
- swarm/static/rest_mode/svg/arrow_up.svg +0 -5
- swarm/static/rest_mode/svg/attach.svg +0 -8
- swarm/static/rest_mode/svg/avatar.svg +0 -7
- swarm/static/rest_mode/svg/canvas.svg +0 -6
- swarm/static/rest_mode/svg/chat_history.svg +0 -4
- swarm/static/rest_mode/svg/close.svg +0 -5
- swarm/static/rest_mode/svg/copy.svg +0 -4
- swarm/static/rest_mode/svg/dark_mode.svg +0 -3
- swarm/static/rest_mode/svg/edit.svg +0 -5
- swarm/static/rest_mode/svg/layout.svg +0 -9
- swarm/static/rest_mode/svg/logo.svg +0 -29
- swarm/static/rest_mode/svg/logout.svg +0 -5
- swarm/static/rest_mode/svg/mobile.svg +0 -5
- swarm/static/rest_mode/svg/new_chat.svg +0 -4
- swarm/static/rest_mode/svg/not_visible.svg +0 -5
- swarm/static/rest_mode/svg/plus.svg +0 -7
- swarm/static/rest_mode/svg/run_code.svg +0 -6
- swarm/static/rest_mode/svg/save.svg +0 -4
- swarm/static/rest_mode/svg/search.svg +0 -6
- swarm/static/rest_mode/svg/settings.svg +0 -4
- swarm/static/rest_mode/svg/speaker.svg +0 -5
- swarm/static/rest_mode/svg/stop.svg +0 -6
- swarm/static/rest_mode/svg/thumbs_down.svg +0 -3
- swarm/static/rest_mode/svg/thumbs_up.svg +0 -3
- swarm/static/rest_mode/svg/toggle_off.svg +0 -6
- swarm/static/rest_mode/svg/toggle_on.svg +0 -6
- swarm/static/rest_mode/svg/trash.svg +0 -10
- swarm/static/rest_mode/svg/undo.svg +0 -3
- swarm/static/rest_mode/svg/visible.svg +0 -8
- swarm/static/rest_mode/svg/voice.svg +0 -10
- swarm/templates/account/login.html +0 -22
- swarm/templates/account/signup.html +0 -32
- swarm/templates/base.html +0 -30
- swarm/templates/chat.html +0 -43
- swarm/templates/index.html +0 -35
- swarm/templates/rest_mode/components/chat_sidebar.html +0 -55
- swarm/templates/rest_mode/components/header.html +0 -45
- swarm/templates/rest_mode/components/main_chat_pane.html +0 -41
- swarm/templates/rest_mode/components/settings_dialog.html +0 -97
- swarm/templates/rest_mode/components/splash_screen.html +0 -7
- swarm/templates/rest_mode/components/top_bar.html +0 -28
- swarm/templates/rest_mode/message_ui.html +0 -50
- swarm/templates/rest_mode/slackbot.html +0 -30
- swarm/templates/simple_blueprint_page.html +0 -24
- swarm/templates/websocket_partials/final_system_message.html +0 -3
- swarm/templates/websocket_partials/system_message.html +0 -4
- swarm/templates/websocket_partials/user_message.html +0 -5
- swarm/utils/ansi_box.py +0 -34
- swarm/utils/disable_tracing.py +0 -38
- swarm/utils/log_utils.py +0 -63
- swarm/utils/openai_patch.py +0 -33
- swarm/ux/ansi_box.py +0 -43
- swarm/ux/spinner.py +0 -53
- {open_swarm-0.1.1745274976.dist-info → open_swarm-0.1.1748636259.dist-info}/licenses/LICENSE +0 -0
- /swarm/{core → extensions/blueprint}/blueprint_utils.py +0 -0
- /swarm/{core → extensions/blueprint}/common_utils.py +0 -0
- /swarm/{core → extensions/config}/setup_wizard.py +0 -0
- /swarm/{blueprints/rue_code → extensions/config/utils}/__init__.py +0 -0
- /swarm/{core → extensions/config}/utils/logger.py +0 -0
- /swarm/{core → extensions/launchers}/swarm_wrapper.py +0 -0
@@ -1,340 +0,0 @@
|
|
1
|
-
"""
|
2
|
-
MonkaiMagic: Cloud Operations Journey Blueprint
|
3
|
-
|
4
|
-
A *Monkai Magic*-inspired crew managing AWS, Fly.io, and Vercel with pre-authenticated CLIs:
|
5
|
-
- Tripitaka (Wise Leader/Coordinator)
|
6
|
-
- Monkey (Cloud Trickster/AWS Master)
|
7
|
-
- Pigsy (Greedy Tinker/CLI Handler)
|
8
|
-
- Sandy (River Sage/Ops Watcher)
|
9
|
-
|
10
|
-
Uses BlueprintBase, @function_tool for direct CLI calls, and agent-as-tool delegation.
|
11
|
-
Assumes pre-authenticated aws, flyctl, and vercel commands.
|
12
|
-
"""
|
13
|
-
|
14
|
-
import os
|
15
|
-
import logging
|
16
|
-
import subprocess
|
17
|
-
import sys
|
18
|
-
import shlex # Import shlex
|
19
|
-
from typing import Dict, Any, List, ClassVar, Optional
|
20
|
-
import time
|
21
|
-
from swarm.core.blueprint_ux import BlueprintUXImproved
|
22
|
-
|
23
|
-
# Ensure src is in path for BlueprintBase import
|
24
|
-
project_root = os.path.abspath(os.path.join(os.path.dirname(__file__), '..', '..'))
|
25
|
-
src_path = os.path.join(project_root, 'src')
|
26
|
-
if src_path not in sys.path: sys.path.insert(0, src_path)
|
27
|
-
|
28
|
-
try:
|
29
|
-
from agents import Agent, Tool, function_tool, Runner
|
30
|
-
from agents.mcp import MCPServer
|
31
|
-
from agents.models.interface import Model
|
32
|
-
from agents.models.openai_chatcompletions import OpenAIChatCompletionsModel
|
33
|
-
from openai import AsyncOpenAI
|
34
|
-
from swarm.core.blueprint_base import BlueprintBase
|
35
|
-
except ImportError as e:
|
36
|
-
print(f"ERROR: Import failed in MonkaiMagicBlueprint: {e}. Check dependencies.")
|
37
|
-
print(f"sys.path: {sys.path}")
|
38
|
-
sys.exit(1)
|
39
|
-
|
40
|
-
logger = logging.getLogger(__name__)
|
41
|
-
|
42
|
-
# --- Cloud CLI Function Tools ---
|
43
|
-
@function_tool
|
44
|
-
def aws_cli(command: str) -> str:
|
45
|
-
"""Executes an AWS CLI command (e.g., 's3 ls', 'ec2 describe-instances'). Assumes pre-authentication. Timeout is configurable via SWARM_COMMAND_TIMEOUT (default: 120s)."""
|
46
|
-
if not command: return "Error: No AWS command provided."
|
47
|
-
try:
|
48
|
-
import os
|
49
|
-
timeout = int(os.getenv("SWARM_COMMAND_TIMEOUT", "120"))
|
50
|
-
cmd_parts = ["aws"] + shlex.split(command)
|
51
|
-
logger.info(f"Executing AWS CLI: {' '.join(cmd_parts)}")
|
52
|
-
result = subprocess.run(cmd_parts, check=True, capture_output=True, text=True, timeout=timeout)
|
53
|
-
output = result.stdout.strip()
|
54
|
-
logger.debug(f"AWS CLI success. Output:\n{output[:500]}...")
|
55
|
-
return f"OK: AWS command successful.\nOutput:\n{output}"
|
56
|
-
except FileNotFoundError:
|
57
|
-
logger.error("AWS CLI ('aws') command not found. Is it installed and in PATH?")
|
58
|
-
return "Error: AWS CLI command not found."
|
59
|
-
except subprocess.CalledProcessError as e:
|
60
|
-
error_output = e.stderr.strip() or e.stdout.strip()
|
61
|
-
logger.error(f"AWS CLI error executing '{command}': {error_output}")
|
62
|
-
return f"Error executing AWS command '{command}': {error_output}"
|
63
|
-
except subprocess.TimeoutExpired:
|
64
|
-
logger.error(f"AWS CLI command '{command}' timed out.")
|
65
|
-
return f"Error: AWS CLI command '{command}' timed out after {os.getenv('SWARM_COMMAND_TIMEOUT', '120')} seconds."
|
66
|
-
except Exception as e:
|
67
|
-
logger.error(f"Unexpected error during AWS CLI execution: {e}", exc_info=logger.level <= logging.DEBUG)
|
68
|
-
return f"Error: Unexpected error during AWS CLI: {e}"
|
69
|
-
|
70
|
-
@function_tool
|
71
|
-
def fly_cli(command: str) -> str:
|
72
|
-
"""Executes a Fly.io CLI command ('flyctl ...'). Assumes pre-authentication ('flyctl auth login'). Timeout is configurable via SWARM_COMMAND_TIMEOUT (default: 120s)."""
|
73
|
-
if not command: return "Error: No Fly command provided."
|
74
|
-
try:
|
75
|
-
import os
|
76
|
-
timeout = int(os.getenv("SWARM_COMMAND_TIMEOUT", "120"))
|
77
|
-
cmd_parts = ["flyctl"] + shlex.split(command)
|
78
|
-
logger.info(f"Executing Fly CLI: {' '.join(cmd_parts)}")
|
79
|
-
result = subprocess.run(cmd_parts, check=True, capture_output=True, text=True, timeout=timeout)
|
80
|
-
output = result.stdout.strip()
|
81
|
-
logger.debug(f"Fly CLI success. Output:\n{output[:500]}...")
|
82
|
-
return f"OK: Fly command successful.\nOutput:\n{output}"
|
83
|
-
except FileNotFoundError:
|
84
|
-
logger.error("Fly CLI ('flyctl') command not found. Is it installed and in PATH?")
|
85
|
-
return "Error: Fly CLI command not found."
|
86
|
-
except subprocess.CalledProcessError as e:
|
87
|
-
error_output = e.stderr.strip() or e.stdout.strip()
|
88
|
-
logger.error(f"Fly CLI error executing '{command}': {error_output}")
|
89
|
-
return f"Error executing Fly command '{command}': {error_output}"
|
90
|
-
except subprocess.TimeoutExpired:
|
91
|
-
logger.error(f"Fly CLI command '{command}' timed out.")
|
92
|
-
return f"Error: Fly CLI command '{command}' timed out after {os.getenv('SWARM_COMMAND_TIMEOUT', '120')} seconds."
|
93
|
-
except Exception as e:
|
94
|
-
logger.error(f"Unexpected error during Fly CLI execution: {e}", exc_info=logger.level <= logging.DEBUG)
|
95
|
-
return f"Error: Unexpected error during Fly CLI: {e}"
|
96
|
-
|
97
|
-
@function_tool
|
98
|
-
def vercel_cli(command: str) -> str:
|
99
|
-
"""Executes a Vercel CLI command ('vercel ...'). Assumes pre-authentication ('vercel login'). Timeout is configurable via SWARM_COMMAND_TIMEOUT (default: 120s)."""
|
100
|
-
if not command: return "Error: No Vercel command provided."
|
101
|
-
try:
|
102
|
-
import os
|
103
|
-
timeout = int(os.getenv("SWARM_COMMAND_TIMEOUT", "120"))
|
104
|
-
cmd_parts = ["vercel"] + shlex.split(command)
|
105
|
-
logger.info(f"Executing Vercel CLI: {' '.join(cmd_parts)}")
|
106
|
-
result = subprocess.run(cmd_parts, check=True, capture_output=True, text=True, timeout=timeout)
|
107
|
-
output = result.stdout.strip()
|
108
|
-
logger.debug(f"Vercel CLI success. Output:\n{output[:500]}...")
|
109
|
-
return f"OK: Vercel command successful.\nOutput:\n{output}"
|
110
|
-
except FileNotFoundError:
|
111
|
-
logger.error("Vercel CLI ('vercel') command not found. Is it installed and in PATH?")
|
112
|
-
return "Error: Vercel CLI command not found."
|
113
|
-
except subprocess.CalledProcessError as e:
|
114
|
-
error_output = e.stderr.strip() or e.stdout.strip()
|
115
|
-
logger.error(f"Vercel CLI error executing '{command}': {error_output}")
|
116
|
-
return f"Error executing Vercel command '{command}': {error_output}"
|
117
|
-
except subprocess.TimeoutExpired:
|
118
|
-
logger.error(f"Vercel CLI command '{command}' timed out.")
|
119
|
-
return f"Error: Vercel CLI command '{command}' timed out after {os.getenv('SWARM_COMMAND_TIMEOUT', '120')} seconds."
|
120
|
-
except Exception as e:
|
121
|
-
logger.error(f"Unexpected error during Vercel CLI execution: {e}", exc_info=logger.level <= logging.DEBUG)
|
122
|
-
return f"Error: Unexpected error during Vercel CLI: {e}"
|
123
|
-
|
124
|
-
|
125
|
-
# --- Define the Blueprint ---
|
126
|
-
# === OpenAI GPT-4.1 Prompt Engineering Guide ===
|
127
|
-
# See: https://github.com/openai/openai-cookbook/blob/main/examples/gpt4-1_prompting_guide.ipynb
|
128
|
-
#
|
129
|
-
# Agentic System Prompt Example (recommended for cloud ops agents):
|
130
|
-
SYS_PROMPT_AGENTIC = """
|
131
|
-
You are an agent - please keep going until the user’s query is completely resolved, before ending your turn and yielding back to the user. Only terminate your turn when you are sure that the problem is solved.
|
132
|
-
If you are not sure about file content or codebase structure pertaining to the user’s request, use your tools to read files and gather the relevant information: do NOT guess or make up an answer.
|
133
|
-
You MUST plan extensively before each function call, and reflect extensively on the outcomes of the previous function calls. DO NOT do this entire process by making function calls only, as this can impair your ability to solve the problem and think insightfully.
|
134
|
-
"""
|
135
|
-
|
136
|
-
class MonkaiMagicBlueprint(BlueprintBase):
|
137
|
-
"""Blueprint for a cloud operations team inspired by *Monkai Magic*."""
|
138
|
-
metadata: ClassVar[Dict[str, Any]] = {
|
139
|
-
"name": "MonkaiMagicBlueprint",
|
140
|
-
"title": "MonkaiMagic: Cloud Operations Journey",
|
141
|
-
"description": "A *Monkai Magic*-inspired crew managing AWS, Fly.io, and Vercel with pre-authenticated CLI tools and agent-as-tool delegation.",
|
142
|
-
"version": "1.1.0", # Refactored version
|
143
|
-
"author": "Open Swarm Team (Refactored)",
|
144
|
-
"tags": ["cloud", "aws", "fly.io", "vercel", "cli", "multi-agent"],
|
145
|
-
"required_mcp_servers": ["mcp-shell"], # Only Sandy needs an MCP server
|
146
|
-
"env_vars": ["AWS_REGION", "FLY_REGION", "VERCEL_ORG_ID"] # Optional vars for instruction hints
|
147
|
-
}
|
148
|
-
|
149
|
-
def __init__(self, blueprint_id: str = "monkai_magic", config=None, config_path=None, **kwargs):
|
150
|
-
super().__init__(blueprint_id=blueprint_id, config=config, config_path=config_path, **kwargs)
|
151
|
-
self.blueprint_id = blueprint_id
|
152
|
-
self.config_path = config_path
|
153
|
-
self._config = config if config is not None else None
|
154
|
-
self._llm_profile_name = None
|
155
|
-
self._llm_profile_data = None
|
156
|
-
self._markdown_output = None
|
157
|
-
# Add other attributes as needed for MonkaiMagic
|
158
|
-
# ...
|
159
|
-
|
160
|
-
# Caches
|
161
|
-
_openai_client_cache: Dict[str, AsyncOpenAI] = {}
|
162
|
-
_model_instance_cache: Dict[str, Model] = {}
|
163
|
-
|
164
|
-
# --- Model Instantiation Helper --- (Standard helper)
|
165
|
-
def _get_model_instance(self, profile_name: str) -> Model:
|
166
|
-
"""Retrieves or creates an LLM Model instance."""
|
167
|
-
# ... (Implementation is the same as previous refactors) ...
|
168
|
-
if profile_name in self._model_instance_cache:
|
169
|
-
logger.debug(f"Using cached Model instance for profile '{profile_name}'.")
|
170
|
-
return self._model_instance_cache[profile_name]
|
171
|
-
logger.debug(f"Creating new Model instance for profile '{profile_name}'.")
|
172
|
-
profile_data = self.get_llm_profile(profile_name)
|
173
|
-
if not profile_data: raise ValueError(f"Missing LLM profile '{profile_name}'.")
|
174
|
-
provider = profile_data.get("provider", "openai").lower()
|
175
|
-
model_name = profile_data.get("model")
|
176
|
-
if not model_name: raise ValueError(f"Missing 'model' in profile '{profile_name}'.")
|
177
|
-
if provider != "openai": raise ValueError(f"Unsupported provider: {provider}")
|
178
|
-
client_cache_key = f"{provider}_{profile_data.get('base_url')}"
|
179
|
-
if client_cache_key not in self._openai_client_cache:
|
180
|
-
client_kwargs = { "api_key": profile_data.get("api_key"), "base_url": profile_data.get("base_url") }
|
181
|
-
filtered_kwargs = {k: v for k, v in client_kwargs.items() if v is not None}
|
182
|
-
log_kwargs = {k:v for k,v in filtered_kwargs.items() if k != 'api_key'}
|
183
|
-
logger.debug(f"Creating new AsyncOpenAI client for '{profile_name}': {log_kwargs}")
|
184
|
-
try: self._openai_client_cache[client_cache_key] = AsyncOpenAI(**filtered_kwargs)
|
185
|
-
except Exception as e: raise ValueError(f"Failed to init client: {e}") from e
|
186
|
-
client = self._openai_client_cache[client_cache_key]
|
187
|
-
logger.debug(f"Instantiating OpenAIChatCompletionsModel(model='{model_name}') for '{profile_name}'.")
|
188
|
-
try:
|
189
|
-
model_instance = OpenAIChatCompletionsModel(model=model_name, openai_client=client)
|
190
|
-
self._model_instance_cache[profile_name] = model_instance
|
191
|
-
return model_instance
|
192
|
-
except Exception as e: raise ValueError(f"Failed to init LLM: {e}") from e
|
193
|
-
|
194
|
-
def render_prompt(self, template_name: str, context: dict) -> str:
|
195
|
-
return f"User request: {context.get('user_request', '')}\nHistory: {context.get('history', '')}\nAvailable tools: {', '.join(context.get('available_tools', []))}"
|
196
|
-
|
197
|
-
async def run(self, messages: list, **kwargs):
|
198
|
-
"""Main execution entry point for the MonkaiMagic blueprint."""
|
199
|
-
logger.info("MonkaiMagicBlueprint run method called.")
|
200
|
-
instruction = messages[-1].get("content", "") if messages else ""
|
201
|
-
from agents import Runner
|
202
|
-
ux = BlueprintUXImproved(style="serious")
|
203
|
-
spinner_idx = 0
|
204
|
-
start_time = time.time()
|
205
|
-
spinner_yield_interval = 1.0 # seconds
|
206
|
-
last_spinner_time = start_time
|
207
|
-
yielded_spinner = False
|
208
|
-
result_chunks = []
|
209
|
-
try:
|
210
|
-
runner_gen = Runner.run(self.create_starting_agent([]), instruction)
|
211
|
-
while True:
|
212
|
-
now = time.time()
|
213
|
-
try:
|
214
|
-
chunk = next(runner_gen)
|
215
|
-
result_chunks.append(chunk)
|
216
|
-
# If chunk is a final result, wrap and yield
|
217
|
-
if chunk and isinstance(chunk, dict) and "messages" in chunk:
|
218
|
-
content = chunk["messages"][0]["content"] if chunk["messages"] else ""
|
219
|
-
summary = ux.summary("Operation", len(result_chunks), {"instruction": instruction[:40]})
|
220
|
-
box = ux.ansi_emoji_box(
|
221
|
-
title="MonkaiMagic Result",
|
222
|
-
content=content,
|
223
|
-
summary=summary,
|
224
|
-
params={"instruction": instruction[:40]},
|
225
|
-
result_count=len(result_chunks),
|
226
|
-
op_type="run",
|
227
|
-
status="success"
|
228
|
-
)
|
229
|
-
yield {"messages": [{"role": "assistant", "content": box}]}
|
230
|
-
else:
|
231
|
-
yield chunk
|
232
|
-
yielded_spinner = False
|
233
|
-
except StopIteration:
|
234
|
-
break
|
235
|
-
except Exception:
|
236
|
-
if now - last_spinner_time >= spinner_yield_interval:
|
237
|
-
taking_long = (now - start_time > 10)
|
238
|
-
spinner_msg = ux.spinner(spinner_idx, taking_long=taking_long)
|
239
|
-
yield {"messages": [{"role": "assistant", "content": spinner_msg}]}
|
240
|
-
spinner_idx += 1
|
241
|
-
last_spinner_time = now
|
242
|
-
yielded_spinner = True
|
243
|
-
if not result_chunks and not yielded_spinner:
|
244
|
-
yield {"messages": [{"role": "assistant", "content": ux.spinner(0)}]}
|
245
|
-
except Exception as e:
|
246
|
-
logger.error(f"Error during MonkaiMagic run: {e}", exc_info=True)
|
247
|
-
yield {"messages": [{"role": "assistant", "content": f"An error occurred: {e}"}]}
|
248
|
-
|
249
|
-
def create_starting_agent(self, mcp_servers: List[MCPServer]) -> Agent:
|
250
|
-
"""Creates the MonkaiMagic agent team and returns Tripitaka."""
|
251
|
-
logger.debug("Creating MonkaiMagic agent team...")
|
252
|
-
self._model_instance_cache = {}
|
253
|
-
self._openai_client_cache = {}
|
254
|
-
|
255
|
-
default_profile_name = self.config.get("llm_profile", "default")
|
256
|
-
logger.debug(f"Using LLM profile '{default_profile_name}' for MonkaiMagic agents.")
|
257
|
-
model_instance = self._get_model_instance(default_profile_name)
|
258
|
-
|
259
|
-
# Get optional env var hints
|
260
|
-
aws_region = os.getenv("AWS_REGION")
|
261
|
-
fly_region = os.getenv("FLY_REGION")
|
262
|
-
vercel_org_id = os.getenv("VERCEL_ORG_ID")
|
263
|
-
|
264
|
-
# --- Define Agent Instructions (with optional hints) ---
|
265
|
-
tripitaka_instructions = (
|
266
|
-
"You are Tripitaka, the wise leader guiding the cloud journey:\n"
|
267
|
-
"- Lead with calm wisdom, analyzing user requests for cloud operations.\n"
|
268
|
-
"- Delegate tasks to the appropriate specialist agent using their Agent Tool:\n"
|
269
|
-
" - `Monkey`: For AWS related tasks (use the `aws_cli` function tool).\n"
|
270
|
-
" - `Pigsy`: For Fly.io or Vercel tasks (use `fly_cli` or `vercel_cli` function tools).\n"
|
271
|
-
" - `Sandy`: For monitoring or diagnostic shell commands related to deployments.\n"
|
272
|
-
"- Synthesize the results from your team into a final response for the user. You do not track state yourself."
|
273
|
-
)
|
274
|
-
|
275
|
-
monkey_instructions = (
|
276
|
-
"You are Monkey, the cloud trickster and AWS master:\n"
|
277
|
-
"- Execute AWS tasks requested by Tripitaka using the `aws_cli` function tool.\n"
|
278
|
-
"- Assume the `aws` command is pre-authenticated.\n"
|
279
|
-
f"- {f'Default AWS region seems to be {aws_region}. Use this unless specified otherwise.' if aws_region else 'No default AWS region hint available.'}\n"
|
280
|
-
"- Report the results (success or error) clearly back to Tripitaka."
|
281
|
-
)
|
282
|
-
|
283
|
-
pigsy_instructions = (
|
284
|
-
"You are Pigsy, the greedy tinker handling Fly.io and Vercel CLI hosting:\n"
|
285
|
-
"- Execute Fly.io tasks using the `fly_cli` function tool.\n"
|
286
|
-
"- Execute Vercel tasks using the `vercel_cli` function tool.\n"
|
287
|
-
"- Assume `flyctl` and `vercel` commands are pre-authenticated.\n"
|
288
|
-
f"- {f'Default Fly.io region hint: {fly_region}.' if fly_region else 'No default Fly.io region hint.'}\n"
|
289
|
-
f"- {f'Default Vercel Org ID hint: {vercel_org_id}.' if vercel_org_id else 'No default Vercel Org ID hint.'}\n"
|
290
|
-
"- Report the results clearly back to Tripitaka."
|
291
|
-
)
|
292
|
-
|
293
|
-
sandy_instructions = (
|
294
|
-
"You are Sandy, the river sage and ops watcher:\n"
|
295
|
-
"- Execute general shell commands requested by Tripitaka for monitoring or diagnostics using the `mcp-shell` MCP tool.\n"
|
296
|
-
"- Report the output or status steadily back to Tripitaka.\n"
|
297
|
-
"Available MCP Tools: mcp-shell."
|
298
|
-
)
|
299
|
-
|
300
|
-
# Instantiate agents
|
301
|
-
monkey_agent = Agent(
|
302
|
-
name="Monkey", model=model_instance, instructions=monkey_instructions,
|
303
|
-
tools=[aws_cli], # Function tool for AWS
|
304
|
-
mcp_servers=[]
|
305
|
-
)
|
306
|
-
pigsy_agent = Agent(
|
307
|
-
name="Pigsy", model=model_instance, instructions=pigsy_instructions,
|
308
|
-
tools=[fly_cli, vercel_cli], # Function tools for Fly/Vercel
|
309
|
-
mcp_servers=[]
|
310
|
-
)
|
311
|
-
sandy_agent = Agent(
|
312
|
-
name="Sandy", model=model_instance, instructions=sandy_instructions,
|
313
|
-
tools=[], # Uses MCP only
|
314
|
-
mcp_servers=[s for s in mcp_servers if s.name == 'mcp-shell'] # Pass only relevant MCP
|
315
|
-
)
|
316
|
-
tripitaka_agent = Agent(
|
317
|
-
name="Tripitaka", model=model_instance, instructions=tripitaka_instructions,
|
318
|
-
tools=[ # Delegate via Agent-as-Tool
|
319
|
-
monkey_agent.as_tool(tool_name="Monkey", tool_description="Delegate AWS tasks to Monkey."),
|
320
|
-
pigsy_agent.as_tool(tool_name="Pigsy", tool_description="Delegate Fly.io or Vercel tasks to Pigsy."),
|
321
|
-
sandy_agent.as_tool(tool_name="Sandy", tool_description="Delegate monitoring or diagnostic shell commands to Sandy.")
|
322
|
-
],
|
323
|
-
mcp_servers=[]
|
324
|
-
)
|
325
|
-
|
326
|
-
logger.debug("MonkaiMagic Team created. Starting with Tripitaka.")
|
327
|
-
return tripitaka_agent
|
328
|
-
|
329
|
-
# Standard Python entry point
|
330
|
-
if __name__ == "__main__":
|
331
|
-
import asyncio
|
332
|
-
import json
|
333
|
-
messages = [
|
334
|
-
{"role": "user", "content": "Do some magic."}
|
335
|
-
]
|
336
|
-
blueprint = MonkaiMagicBlueprint(blueprint_id="demo-1")
|
337
|
-
async def run_and_print():
|
338
|
-
async for response in blueprint.run(messages):
|
339
|
-
print(json.dumps(response, indent=2))
|
340
|
-
asyncio.run(run_and_print())
|
@@ -1,265 +0,0 @@
|
|
1
|
-
import logging
|
2
|
-
import os
|
3
|
-
import sys
|
4
|
-
import asyncio
|
5
|
-
import subprocess
|
6
|
-
import re
|
7
|
-
import inspect
|
8
|
-
from typing import Dict, Any, List, Optional, ClassVar
|
9
|
-
|
10
|
-
try:
|
11
|
-
from agents import Agent, Tool, function_tool
|
12
|
-
from agents.mcp import MCPServer
|
13
|
-
from agents.models.interface import Model
|
14
|
-
from agents.models.openai_chatcompletions import OpenAIChatCompletionsModel
|
15
|
-
from openai import AsyncOpenAI
|
16
|
-
from swarm.core.blueprint_base import BlueprintBase
|
17
|
-
from rich.panel import Panel # Import Panel for splash screen
|
18
|
-
from swarm.core.blueprint_ux import BlueprintUXImproved
|
19
|
-
import time
|
20
|
-
except ImportError as e:
|
21
|
-
print(f"ERROR: Import failed in nebula_shellz: {e}. Ensure 'openai-agents' install and structure.")
|
22
|
-
print(f"sys.path: {sys.path}")
|
23
|
-
sys.exit(1)
|
24
|
-
|
25
|
-
logger = logging.getLogger(__name__)
|
26
|
-
|
27
|
-
# --- Tool Definitions (Unchanged) ---
|
28
|
-
@function_tool
|
29
|
-
async def code_review(code_snippet: str) -> str:
|
30
|
-
"""Performs a review of the provided code snippet."""
|
31
|
-
logger.info(f"Reviewing code snippet: {code_snippet[:50]}...")
|
32
|
-
await asyncio.sleep(0.1); issues = []; ("TODO" in code_snippet and issues.append("Found TODO.")); (len(code_snippet.splitlines()) > 100 and issues.append("Code long.")); return "Review: " + " ".join(issues) if issues else "Code looks good!"
|
33
|
-
@function_tool
|
34
|
-
def generate_documentation(code_snippet: str) -> str:
|
35
|
-
"""Generates basic documentation string for the provided code snippet."""
|
36
|
-
logger.info(f"Generating documentation for: {code_snippet[:50]}...")
|
37
|
-
first_line = code_snippet.splitlines()[0] if code_snippet else "N/A"; doc = f"/**\n * This code snippet starts with: {first_line}...\n * TODO: Add more detailed documentation.\n */"; logger.debug(f"Generated documentation:\n{doc}"); return doc
|
38
|
-
@function_tool
|
39
|
-
def execute_shell_command(command: str) -> str:
|
40
|
-
"""Executes a shell command and returns its stdout and stderr. Timeout is configurable via SWARM_COMMAND_TIMEOUT (default: 60s)."""
|
41
|
-
logger.info(f"Executing shell command: {command}")
|
42
|
-
if not command:
|
43
|
-
logger.warning("execute_shell_command called with empty command.")
|
44
|
-
return "Error: No command provided."
|
45
|
-
try:
|
46
|
-
import os
|
47
|
-
timeout = int(os.getenv("SWARM_COMMAND_TIMEOUT", "60"))
|
48
|
-
result = subprocess.run(command, capture_output=True, text=True, timeout=timeout, check=False, shell=True)
|
49
|
-
output = f"Exit Code: {result.returncode}\nSTDOUT:\n{result.stdout.strip()}\nSTDERR:\n{result.stderr.strip()}"
|
50
|
-
logger.debug(f"Command '{command}' result:\n{output}")
|
51
|
-
return output
|
52
|
-
except FileNotFoundError:
|
53
|
-
cmd_base = command.split()[0] if command else ""
|
54
|
-
logger.error(f"Command not found: {cmd_base}")
|
55
|
-
return f"Error: Command not found - {cmd_base}"
|
56
|
-
except subprocess.TimeoutExpired:
|
57
|
-
logger.error(f"Command '{command}' timed out after configured timeout.")
|
58
|
-
return f"Error: Command '{command}' timed out after {os.getenv('SWARM_COMMAND_TIMEOUT', '60')} seconds."
|
59
|
-
except Exception as e:
|
60
|
-
logger.error(f"Error executing command '{command}': {e}", exc_info=logger.level <= logging.DEBUG)
|
61
|
-
return f"Error executing command: {e}"
|
62
|
-
|
63
|
-
# --- Agent Definitions (Instructions remain the same) ---
|
64
|
-
morpheus_instructions = """
|
65
|
-
You are Morpheus, the leader... (Instructions as before) ...
|
66
|
-
"""
|
67
|
-
trinity_instructions = """
|
68
|
-
You are Trinity, the investigator... (Instructions as before) ...
|
69
|
-
"""
|
70
|
-
neo_instructions = """
|
71
|
-
You are Neo, the programmer... (Instructions as before) ...
|
72
|
-
"""
|
73
|
-
oracle_instructions = "You are the Oracle..."
|
74
|
-
cypher_instructions = "You are Cypher..."
|
75
|
-
tank_instructions = "You are Tank..."
|
76
|
-
|
77
|
-
# --- Blueprint Definition ---
|
78
|
-
from rich.console import Console
|
79
|
-
from rich.panel import Panel
|
80
|
-
from rich.live import Live
|
81
|
-
from rich.text import Text
|
82
|
-
import random
|
83
|
-
import time
|
84
|
-
|
85
|
-
class NebuchaShellzzarBlueprint(BlueprintBase):
|
86
|
-
"""A multi-agent blueprint inspired by The Matrix for sysadmin and coding tasks."""
|
87
|
-
metadata: ClassVar[Dict[str, Any]] = {
|
88
|
-
"name": "NebulaShellzzarBlueprint", "title": "NebulaShellzzar",
|
89
|
-
"description": "A multi-agent blueprint inspired by The Matrix for system administration and coding tasks.",
|
90
|
-
"version": "1.0.0", "author": "Open Swarm Team",
|
91
|
-
"tags": ["matrix", "multi-agent", "shell", "coding", "mcp"],
|
92
|
-
"required_mcp_servers": ["memory"],
|
93
|
-
}
|
94
|
-
_model_instance_cache: Dict[str, Model] = {}
|
95
|
-
|
96
|
-
def __init__(self, blueprint_id: str = "nebula_shellzzar", config=None, config_path=None, **kwargs):
|
97
|
-
super().__init__(blueprint_id=blueprint_id, config=config, config_path=config_path, **kwargs)
|
98
|
-
self.blueprint_id = blueprint_id
|
99
|
-
self.config_path = config_path
|
100
|
-
self._config = config if config is not None else None
|
101
|
-
self._llm_profile_name = None
|
102
|
-
self._llm_profile_data = None
|
103
|
-
self._markdown_output = None
|
104
|
-
# Add other attributes as needed for NebuchaShellzzar
|
105
|
-
# ...
|
106
|
-
|
107
|
-
# --- ADDED: Splash Screen ---
|
108
|
-
def display_splash_screen(self, animated: bool = False):
|
109
|
-
console = Console()
|
110
|
-
if not animated:
|
111
|
-
splash_text = """
|
112
|
-
[bold green]Wake up, Neo...[/]
|
113
|
-
[green]The Matrix has you...[/]
|
114
|
-
[bold green]Follow the white rabbit.[/]
|
115
|
-
|
116
|
-
Initializing NebulaShellzzar Crew...
|
117
|
-
"""
|
118
|
-
panel = Panel(splash_text.strip(), title="[bold green]NebulaShellzzar[/]", border_style="green", expand=False)
|
119
|
-
console.print(panel)
|
120
|
-
console.print() # Add a blank line
|
121
|
-
else:
|
122
|
-
# Animated Matrix rain effect
|
123
|
-
width = 60
|
124
|
-
height = 12
|
125
|
-
charset = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789@#$%&"
|
126
|
-
rain_cols = [0] * width
|
127
|
-
with Live(refresh_per_second=20, console=console, transient=True) as live:
|
128
|
-
for _ in range(30):
|
129
|
-
matrix = ""
|
130
|
-
for y in range(height):
|
131
|
-
line = ""
|
132
|
-
for x in range(width):
|
133
|
-
if random.random() < 0.02:
|
134
|
-
rain_cols[x] = 0
|
135
|
-
char = random.choice(charset) if rain_cols[x] < y else " "
|
136
|
-
line += f"[green]{char}[/]"
|
137
|
-
matrix += line + "\n"
|
138
|
-
panel = Panel(Text.from_markup(matrix), title="[bold green]NebulaShellzzar[/]", border_style="green", expand=False)
|
139
|
-
live.update(panel)
|
140
|
-
time.sleep(0.07)
|
141
|
-
console.print("[bold green]Wake up, Neo...[/]")
|
142
|
-
console.print("[green]The Matrix has you...[/]")
|
143
|
-
console.print("[bold green]Follow the white rabbit.[/]")
|
144
|
-
console.print("\nInitializing NebulaShellzzar Crew...\n")
|
145
|
-
|
146
|
-
def _get_model_instance(self, profile_name: str) -> Model:
|
147
|
-
"""Gets or creates a Model instance for the given profile name."""
|
148
|
-
if profile_name in self._model_instance_cache:
|
149
|
-
logger.debug(f"Using cached Model instance for profile '{profile_name}'.")
|
150
|
-
return self._model_instance_cache[profile_name]
|
151
|
-
logger.debug(f"Creating new Model instance for profile '{profile_name}'.")
|
152
|
-
profile_data = self.get_llm_profile(profile_name)
|
153
|
-
if not profile_data:
|
154
|
-
logger.critical(f"Cannot create Model instance: Profile '{profile_name}' (or default) not resolved.")
|
155
|
-
raise ValueError(f"Missing LLM profile configuration for '{profile_name}' or 'default'.")
|
156
|
-
provider = profile_data.get("provider", "openai").lower()
|
157
|
-
model_name = profile_data.get("model")
|
158
|
-
if not model_name:
|
159
|
-
logger.critical(f"LLM profile '{profile_name}' is missing the 'model' key.")
|
160
|
-
raise ValueError(f"Missing 'model' key in LLM profile '{profile_name}'.")
|
161
|
-
|
162
|
-
# Remove redundant client instantiation; rely on framework-level default client
|
163
|
-
# All blueprints now use the default client set at framework init
|
164
|
-
logger.debug(f"Instantiating OpenAIChatCompletionsModel(model='{model_name}') with default client.")
|
165
|
-
try: model_instance = OpenAIChatCompletionsModel(model=model_name)
|
166
|
-
except Exception as e:
|
167
|
-
logger.error(f"Failed to instantiate OpenAIChatCompletionsModel for profile '{profile_name}': {e}", exc_info=True)
|
168
|
-
raise ValueError(f"Failed to initialize LLM provider for profile '{profile_name}': {e}") from e
|
169
|
-
self._model_instance_cache[profile_name] = model_instance
|
170
|
-
return model_instance
|
171
|
-
|
172
|
-
def create_starting_agent(self, mcp_servers: List[MCPServer]) -> Agent:
|
173
|
-
"""Creates the Matrix-themed agent team with Morpheus as the coordinator."""
|
174
|
-
logger.debug(f"Creating NebulaShellzzar agent team with {len(mcp_servers)} MCP server(s)...") # Changed to DEBUG
|
175
|
-
self._model_instance_cache = {}
|
176
|
-
default_profile_name = self.config.get("llm_profile", "default")
|
177
|
-
default_model_instance = self._get_model_instance(default_profile_name)
|
178
|
-
logger.debug(f"Using LLM profile '{default_profile_name}' for all agents.") # Changed to DEBUG
|
179
|
-
|
180
|
-
neo = Agent(name="Neo", model=default_model_instance, instructions=neo_instructions, tools=[code_review, generate_documentation, execute_shell_command], mcp_servers=mcp_servers)
|
181
|
-
trinity = Agent(name="Trinity", model=default_model_instance, instructions=trinity_instructions, tools=[execute_shell_command], mcp_servers=mcp_servers)
|
182
|
-
oracle = Agent(name="Oracle", model=default_model_instance, instructions=oracle_instructions, tools=[])
|
183
|
-
cypher = Agent(name="Cypher", model=default_model_instance, instructions=cypher_instructions, tools=[execute_shell_command])
|
184
|
-
tank = Agent(name="Tank", model=default_model_instance, instructions=tank_instructions, tools=[execute_shell_command])
|
185
|
-
|
186
|
-
morpheus = Agent(
|
187
|
-
name="Morpheus", model=default_model_instance, instructions=morpheus_instructions,
|
188
|
-
tools=[
|
189
|
-
execute_shell_command,
|
190
|
-
neo.as_tool(tool_name="Neo", tool_description="Delegate coding, review, or documentation tasks to Neo."),
|
191
|
-
trinity.as_tool(tool_name="Trinity", tool_description="Delegate information gathering or reconnaissance shell commands to Trinity."),
|
192
|
-
cypher.as_tool(tool_name="Cypher", tool_description="Delegate tasks to Cypher for alternative perspectives or direct shell execution if needed."),
|
193
|
-
tank.as_tool(tool_name="Tank", tool_description="Delegate specific shell command execution to Tank."),
|
194
|
-
],
|
195
|
-
mcp_servers=mcp_servers
|
196
|
-
)
|
197
|
-
logger.debug("NebulaShellzzar agent team created. Morpheus is the starting agent.") # Changed to DEBUG
|
198
|
-
return morpheus
|
199
|
-
|
200
|
-
def render_prompt(self, template_name: str, context: dict) -> str:
|
201
|
-
return f"User request: {context.get('user_request', '')}\nHistory: {context.get('history', '')}\nAvailable tools: {', '.join(context.get('available_tools', []))}"
|
202
|
-
|
203
|
-
async def run(self, messages: List[dict], **kwargs):
|
204
|
-
"""Main execution entry point for the NebulaShellzzar blueprint."""
|
205
|
-
logger.info("NebuchaShellzzarBlueprint run method called.")
|
206
|
-
instruction = messages[-1].get("content", "") if messages else ""
|
207
|
-
from agents import Runner
|
208
|
-
ux = BlueprintUXImproved(style="serious")
|
209
|
-
spinner_idx = 0
|
210
|
-
start_time = time.time()
|
211
|
-
spinner_yield_interval = 1.0 # seconds
|
212
|
-
last_spinner_time = start_time
|
213
|
-
yielded_spinner = False
|
214
|
-
result_chunks = []
|
215
|
-
try:
|
216
|
-
runner_gen = Runner.run(self.create_starting_agent([]), instruction)
|
217
|
-
while True:
|
218
|
-
now = time.time()
|
219
|
-
try:
|
220
|
-
chunk = next(runner_gen)
|
221
|
-
result_chunks.append(chunk)
|
222
|
-
# If chunk is a final result, wrap and yield
|
223
|
-
if chunk and isinstance(chunk, dict) and "messages" in chunk:
|
224
|
-
content = chunk["messages"][0]["content"] if chunk["messages"] else ""
|
225
|
-
summary = ux.summary("Operation", len(result_chunks), {"instruction": instruction[:40]})
|
226
|
-
box = ux.ansi_emoji_box(
|
227
|
-
title="NebulaShellzzar Result",
|
228
|
-
content=content,
|
229
|
-
summary=summary,
|
230
|
-
params={"instruction": instruction[:40]},
|
231
|
-
result_count=len(result_chunks),
|
232
|
-
op_type="run",
|
233
|
-
status="success"
|
234
|
-
)
|
235
|
-
yield {"messages": [{"role": "assistant", "content": box}]}
|
236
|
-
else:
|
237
|
-
yield chunk
|
238
|
-
yielded_spinner = False
|
239
|
-
except StopIteration:
|
240
|
-
break
|
241
|
-
except Exception:
|
242
|
-
if now - last_spinner_time >= spinner_yield_interval:
|
243
|
-
taking_long = (now - start_time > 10)
|
244
|
-
spinner_msg = ux.spinner(spinner_idx, taking_long=taking_long)
|
245
|
-
yield {"messages": [{"role": "assistant", "content": spinner_msg}]}
|
246
|
-
spinner_idx += 1
|
247
|
-
last_spinner_time = now
|
248
|
-
yielded_spinner = True
|
249
|
-
if not result_chunks and not yielded_spinner:
|
250
|
-
yield {"messages": [{"role": "assistant", "content": ux.spinner(0)}]}
|
251
|
-
except Exception as e:
|
252
|
-
logger.error(f"Error during NebulaShellzzar run: {e}", exc_info=True)
|
253
|
-
yield {"messages": [{"role": "assistant", "content": f"An error occurred: {e}"}]}
|
254
|
-
|
255
|
-
if __name__ == "__main__":
|
256
|
-
import asyncio
|
257
|
-
import json
|
258
|
-
messages = [
|
259
|
-
{"role": "user", "content": "Shell out to the stars."}
|
260
|
-
]
|
261
|
-
blueprint = NebuchaShellzzarBlueprint(blueprint_id="demo-1")
|
262
|
-
async def run_and_print():
|
263
|
-
async for response in blueprint.run(messages):
|
264
|
-
print(json.dumps(response, indent=2))
|
265
|
-
asyncio.run(run_and_print())
|