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.
Files changed (295) hide show
  1. open_swarm-0.1.1748636259.dist-info/METADATA +188 -0
  2. open_swarm-0.1.1748636259.dist-info/RECORD +82 -0
  3. {open_swarm-0.1.1745274976.dist-info → open_swarm-0.1.1748636259.dist-info}/WHEEL +2 -1
  4. open_swarm-0.1.1748636259.dist-info/entry_points.txt +3 -0
  5. open_swarm-0.1.1748636259.dist-info/top_level.txt +1 -0
  6. swarm/agent/agent.py +49 -0
  7. swarm/auth.py +48 -113
  8. swarm/consumers.py +0 -19
  9. swarm/extensions/blueprint/__init__.py +16 -30
  10. swarm/{core → extensions/blueprint}/agent_utils.py +1 -1
  11. swarm/extensions/blueprint/blueprint_base.py +458 -0
  12. swarm/extensions/blueprint/blueprint_discovery.py +112 -0
  13. swarm/extensions/blueprint/output_utils.py +95 -0
  14. swarm/{core → extensions/blueprint}/spinner.py +21 -30
  15. swarm/extensions/cli/cli_args.py +0 -6
  16. swarm/extensions/cli/commands/blueprint_management.py +9 -47
  17. swarm/extensions/cli/commands/config_management.py +6 -5
  18. swarm/extensions/cli/commands/edit_config.py +7 -16
  19. swarm/extensions/cli/commands/list_blueprints.py +1 -1
  20. swarm/extensions/cli/commands/validate_env.py +4 -11
  21. swarm/extensions/cli/commands/validate_envvars.py +6 -6
  22. swarm/extensions/cli/interactive_shell.py +2 -16
  23. swarm/extensions/config/config_loader.py +201 -107
  24. swarm/{core → extensions/config}/config_manager.py +38 -50
  25. swarm/{core → extensions/config}/server_config.py +0 -32
  26. swarm/extensions/launchers/build_launchers.py +14 -0
  27. swarm/{core → extensions/launchers}/build_swarm_wrapper.py +0 -0
  28. swarm/extensions/launchers/swarm_api.py +64 -8
  29. swarm/extensions/launchers/swarm_cli.py +300 -8
  30. swarm/llm/chat_completion.py +195 -0
  31. swarm/serializers.py +5 -96
  32. swarm/settings.py +111 -99
  33. swarm/urls.py +74 -57
  34. swarm/utils/context_utils.py +4 -10
  35. swarm/utils/general_utils.py +0 -21
  36. swarm/utils/redact.py +36 -23
  37. swarm/views/api_views.py +39 -48
  38. swarm/views/chat_views.py +70 -237
  39. swarm/views/core_views.py +87 -80
  40. swarm/views/model_views.py +121 -64
  41. swarm/views/utils.py +441 -65
  42. swarm/views/web_views.py +2 -2
  43. open_swarm-0.1.1745274976.dist-info/METADATA +0 -874
  44. open_swarm-0.1.1745274976.dist-info/RECORD +0 -318
  45. open_swarm-0.1.1745274976.dist-info/entry_points.txt +0 -4
  46. swarm/blueprints/README.md +0 -68
  47. swarm/blueprints/blueprint_audit_status.json +0 -27
  48. swarm/blueprints/chatbot/README.md +0 -40
  49. swarm/blueprints/chatbot/blueprint_chatbot.py +0 -471
  50. swarm/blueprints/chatbot/metadata.json +0 -23
  51. swarm/blueprints/chatbot/templates/chatbot/chatbot.html +0 -33
  52. swarm/blueprints/chucks_angels/README.md +0 -11
  53. swarm/blueprints/chucks_angels/blueprint_chucks_angels.py +0 -7
  54. swarm/blueprints/chucks_angels/test_basic.py +0 -3
  55. swarm/blueprints/codey/CODEY.md +0 -15
  56. swarm/blueprints/codey/README.md +0 -115
  57. swarm/blueprints/codey/blueprint_codey.py +0 -1072
  58. swarm/blueprints/codey/codey_cli.py +0 -373
  59. swarm/blueprints/codey/instructions.md +0 -17
  60. swarm/blueprints/codey/metadata.json +0 -23
  61. swarm/blueprints/common/operation_box_utils.py +0 -83
  62. swarm/blueprints/digitalbutlers/README.md +0 -11
  63. swarm/blueprints/digitalbutlers/__init__.py +0 -1
  64. swarm/blueprints/digitalbutlers/blueprint_digitalbutlers.py +0 -7
  65. swarm/blueprints/digitalbutlers/test_basic.py +0 -3
  66. swarm/blueprints/divine_code/README.md +0 -3
  67. swarm/blueprints/divine_code/__init__.py +0 -10
  68. swarm/blueprints/divine_code/apps.py +0 -11
  69. swarm/blueprints/divine_code/blueprint_divine_code.py +0 -270
  70. swarm/blueprints/django_chat/apps.py +0 -6
  71. swarm/blueprints/django_chat/blueprint_django_chat.py +0 -268
  72. swarm/blueprints/django_chat/templates/django_chat/django_chat_webpage.html +0 -37
  73. swarm/blueprints/django_chat/urls.py +0 -8
  74. swarm/blueprints/django_chat/views.py +0 -32
  75. swarm/blueprints/echocraft/blueprint_echocraft.py +0 -384
  76. swarm/blueprints/flock/README.md +0 -11
  77. swarm/blueprints/flock/__init__.py +0 -8
  78. swarm/blueprints/flock/blueprint_flock.py +0 -7
  79. swarm/blueprints/flock/test_basic.py +0 -3
  80. swarm/blueprints/geese/README.md +0 -97
  81. swarm/blueprints/geese/blueprint_geese.py +0 -803
  82. swarm/blueprints/geese/geese_cli.py +0 -102
  83. swarm/blueprints/jeeves/README.md +0 -41
  84. swarm/blueprints/jeeves/blueprint_jeeves.py +0 -722
  85. swarm/blueprints/jeeves/jeeves_cli.py +0 -55
  86. swarm/blueprints/jeeves/metadata.json +0 -24
  87. swarm/blueprints/mcp_demo/blueprint_mcp_demo.py +0 -473
  88. swarm/blueprints/messenger/templates/messenger/messenger.html +0 -46
  89. swarm/blueprints/mission_improbable/blueprint_mission_improbable.py +0 -423
  90. swarm/blueprints/monkai_magic/blueprint_monkai_magic.py +0 -340
  91. swarm/blueprints/nebula_shellz/blueprint_nebula_shellz.py +0 -265
  92. swarm/blueprints/omniplex/blueprint_omniplex.py +0 -298
  93. swarm/blueprints/poets/blueprint_poets.py +0 -546
  94. swarm/blueprints/poets/poets_cli.py +0 -23
  95. swarm/blueprints/rue_code/README.md +0 -8
  96. swarm/blueprints/rue_code/blueprint_rue_code.py +0 -448
  97. swarm/blueprints/rue_code/rue_code_cli.py +0 -43
  98. swarm/blueprints/stewie/apps.py +0 -12
  99. swarm/blueprints/stewie/blueprint_family_ties.py +0 -349
  100. swarm/blueprints/stewie/models.py +0 -19
  101. swarm/blueprints/stewie/serializers.py +0 -10
  102. swarm/blueprints/stewie/settings.py +0 -17
  103. swarm/blueprints/stewie/urls.py +0 -11
  104. swarm/blueprints/stewie/views.py +0 -26
  105. swarm/blueprints/suggestion/blueprint_suggestion.py +0 -222
  106. swarm/blueprints/whinge_surf/README.md +0 -22
  107. swarm/blueprints/whinge_surf/__init__.py +0 -1
  108. swarm/blueprints/whinge_surf/blueprint_whinge_surf.py +0 -565
  109. swarm/blueprints/whinge_surf/whinge_surf_cli.py +0 -99
  110. swarm/blueprints/whiskeytango_foxtrot/__init__.py +0 -0
  111. swarm/blueprints/whiskeytango_foxtrot/apps.py +0 -11
  112. swarm/blueprints/whiskeytango_foxtrot/blueprint_whiskeytango_foxtrot.py +0 -339
  113. swarm/blueprints/zeus/__init__.py +0 -2
  114. swarm/blueprints/zeus/apps.py +0 -4
  115. swarm/blueprints/zeus/blueprint_zeus.py +0 -270
  116. swarm/blueprints/zeus/zeus_cli.py +0 -13
  117. swarm/cli/async_input.py +0 -65
  118. swarm/cli/async_input_demo.py +0 -32
  119. swarm/core/blueprint_base.py +0 -769
  120. swarm/core/blueprint_discovery.py +0 -125
  121. swarm/core/blueprint_runner.py +0 -59
  122. swarm/core/blueprint_ux.py +0 -109
  123. swarm/core/build_launchers.py +0 -15
  124. swarm/core/cli/__init__.py +0 -1
  125. swarm/core/cli/commands/__init__.py +0 -1
  126. swarm/core/cli/commands/blueprint_management.py +0 -7
  127. swarm/core/cli/interactive_shell.py +0 -14
  128. swarm/core/cli/main.py +0 -50
  129. swarm/core/cli/utils/__init__.py +0 -1
  130. swarm/core/cli/utils/discover_commands.py +0 -18
  131. swarm/core/config_loader.py +0 -122
  132. swarm/core/output_utils.py +0 -193
  133. swarm/core/session_logger.py +0 -42
  134. swarm/core/slash_commands.py +0 -89
  135. swarm/core/swarm_api.py +0 -68
  136. swarm/core/swarm_cli.py +0 -216
  137. swarm/core/utils/__init__.py +0 -0
  138. swarm/extensions/blueprint/cli_handler.py +0 -197
  139. swarm/extensions/blueprint/runnable_blueprint.py +0 -42
  140. swarm/extensions/cli/utils/__init__.py +0 -1
  141. swarm/extensions/cli/utils/async_input.py +0 -46
  142. swarm/extensions/cli/utils/prompt_user.py +0 -3
  143. swarm/management/__init__.py +0 -0
  144. swarm/management/commands/__init__.py +0 -0
  145. swarm/management/commands/runserver.py +0 -58
  146. swarm/middleware.py +0 -65
  147. swarm/permissions.py +0 -38
  148. swarm/static/contrib/fonts/fontawesome-webfont.ttf +0 -7
  149. swarm/static/contrib/fonts/fontawesome-webfont.woff +0 -7
  150. swarm/static/contrib/fonts/fontawesome-webfont.woff2 +0 -7
  151. swarm/static/contrib/markedjs/marked.min.js +0 -6
  152. swarm/static/contrib/tabler-icons/adjustments-horizontal.svg +0 -27
  153. swarm/static/contrib/tabler-icons/alert-triangle.svg +0 -21
  154. swarm/static/contrib/tabler-icons/archive.svg +0 -21
  155. swarm/static/contrib/tabler-icons/artboard.svg +0 -27
  156. swarm/static/contrib/tabler-icons/automatic-gearbox.svg +0 -23
  157. swarm/static/contrib/tabler-icons/box-multiple.svg +0 -19
  158. swarm/static/contrib/tabler-icons/carambola.svg +0 -19
  159. swarm/static/contrib/tabler-icons/copy.svg +0 -20
  160. swarm/static/contrib/tabler-icons/download.svg +0 -21
  161. swarm/static/contrib/tabler-icons/edit.svg +0 -21
  162. swarm/static/contrib/tabler-icons/filled/carambola.svg +0 -13
  163. swarm/static/contrib/tabler-icons/filled/paint.svg +0 -13
  164. swarm/static/contrib/tabler-icons/headset.svg +0 -22
  165. swarm/static/contrib/tabler-icons/layout-sidebar-left-collapse.svg +0 -21
  166. swarm/static/contrib/tabler-icons/layout-sidebar-left-expand.svg +0 -21
  167. swarm/static/contrib/tabler-icons/layout-sidebar-right-collapse.svg +0 -21
  168. swarm/static/contrib/tabler-icons/layout-sidebar-right-expand.svg +0 -21
  169. swarm/static/contrib/tabler-icons/message-chatbot.svg +0 -22
  170. swarm/static/contrib/tabler-icons/message-star.svg +0 -22
  171. swarm/static/contrib/tabler-icons/message-x.svg +0 -23
  172. swarm/static/contrib/tabler-icons/message.svg +0 -21
  173. swarm/static/contrib/tabler-icons/paperclip.svg +0 -18
  174. swarm/static/contrib/tabler-icons/playlist-add.svg +0 -22
  175. swarm/static/contrib/tabler-icons/robot.svg +0 -26
  176. swarm/static/contrib/tabler-icons/search.svg +0 -19
  177. swarm/static/contrib/tabler-icons/settings.svg +0 -20
  178. swarm/static/contrib/tabler-icons/thumb-down.svg +0 -19
  179. swarm/static/contrib/tabler-icons/thumb-up.svg +0 -19
  180. swarm/static/css/dropdown.css +0 -22
  181. swarm/static/htmx/htmx.min.js +0 -0
  182. swarm/static/js/dropdown.js +0 -23
  183. swarm/static/rest_mode/css/base.css +0 -470
  184. swarm/static/rest_mode/css/chat-history.css +0 -286
  185. swarm/static/rest_mode/css/chat.css +0 -251
  186. swarm/static/rest_mode/css/chatbot.css +0 -74
  187. swarm/static/rest_mode/css/chatgpt.css +0 -62
  188. swarm/static/rest_mode/css/colors/corporate.css +0 -74
  189. swarm/static/rest_mode/css/colors/pastel.css +0 -81
  190. swarm/static/rest_mode/css/colors/tropical.css +0 -82
  191. swarm/static/rest_mode/css/general.css +0 -142
  192. swarm/static/rest_mode/css/layout.css +0 -167
  193. swarm/static/rest_mode/css/layouts/messenger-layout.css +0 -17
  194. swarm/static/rest_mode/css/layouts/minimalist-layout.css +0 -57
  195. swarm/static/rest_mode/css/layouts/mobile-layout.css +0 -8
  196. swarm/static/rest_mode/css/messages.css +0 -84
  197. swarm/static/rest_mode/css/messenger.css +0 -135
  198. swarm/static/rest_mode/css/settings.css +0 -91
  199. swarm/static/rest_mode/css/simple.css +0 -44
  200. swarm/static/rest_mode/css/slack.css +0 -58
  201. swarm/static/rest_mode/css/style.css +0 -156
  202. swarm/static/rest_mode/css/theme.css +0 -30
  203. swarm/static/rest_mode/css/toast.css +0 -40
  204. swarm/static/rest_mode/js/auth.js +0 -9
  205. swarm/static/rest_mode/js/blueprint.js +0 -41
  206. swarm/static/rest_mode/js/blueprintUtils.js +0 -12
  207. swarm/static/rest_mode/js/chatLogic.js +0 -79
  208. swarm/static/rest_mode/js/debug.js +0 -63
  209. swarm/static/rest_mode/js/events.js +0 -98
  210. swarm/static/rest_mode/js/main.js +0 -19
  211. swarm/static/rest_mode/js/messages.js +0 -264
  212. swarm/static/rest_mode/js/messengerLogic.js +0 -355
  213. swarm/static/rest_mode/js/modules/apiService.js +0 -84
  214. swarm/static/rest_mode/js/modules/blueprintManager.js +0 -162
  215. swarm/static/rest_mode/js/modules/chatHistory.js +0 -110
  216. swarm/static/rest_mode/js/modules/debugLogger.js +0 -14
  217. swarm/static/rest_mode/js/modules/eventHandlers.js +0 -107
  218. swarm/static/rest_mode/js/modules/messageProcessor.js +0 -120
  219. swarm/static/rest_mode/js/modules/state.js +0 -7
  220. swarm/static/rest_mode/js/modules/userInteractions.js +0 -29
  221. swarm/static/rest_mode/js/modules/validation.js +0 -23
  222. swarm/static/rest_mode/js/rendering.js +0 -119
  223. swarm/static/rest_mode/js/settings.js +0 -130
  224. swarm/static/rest_mode/js/sidebar.js +0 -94
  225. swarm/static/rest_mode/js/simpleLogic.js +0 -37
  226. swarm/static/rest_mode/js/slackLogic.js +0 -66
  227. swarm/static/rest_mode/js/splash.js +0 -76
  228. swarm/static/rest_mode/js/theme.js +0 -111
  229. swarm/static/rest_mode/js/toast.js +0 -36
  230. swarm/static/rest_mode/js/ui.js +0 -265
  231. swarm/static/rest_mode/js/validation.js +0 -57
  232. swarm/static/rest_mode/svg/animated_spinner.svg +0 -12
  233. swarm/static/rest_mode/svg/arrow_down.svg +0 -5
  234. swarm/static/rest_mode/svg/arrow_left.svg +0 -5
  235. swarm/static/rest_mode/svg/arrow_right.svg +0 -5
  236. swarm/static/rest_mode/svg/arrow_up.svg +0 -5
  237. swarm/static/rest_mode/svg/attach.svg +0 -8
  238. swarm/static/rest_mode/svg/avatar.svg +0 -7
  239. swarm/static/rest_mode/svg/canvas.svg +0 -6
  240. swarm/static/rest_mode/svg/chat_history.svg +0 -4
  241. swarm/static/rest_mode/svg/close.svg +0 -5
  242. swarm/static/rest_mode/svg/copy.svg +0 -4
  243. swarm/static/rest_mode/svg/dark_mode.svg +0 -3
  244. swarm/static/rest_mode/svg/edit.svg +0 -5
  245. swarm/static/rest_mode/svg/layout.svg +0 -9
  246. swarm/static/rest_mode/svg/logo.svg +0 -29
  247. swarm/static/rest_mode/svg/logout.svg +0 -5
  248. swarm/static/rest_mode/svg/mobile.svg +0 -5
  249. swarm/static/rest_mode/svg/new_chat.svg +0 -4
  250. swarm/static/rest_mode/svg/not_visible.svg +0 -5
  251. swarm/static/rest_mode/svg/plus.svg +0 -7
  252. swarm/static/rest_mode/svg/run_code.svg +0 -6
  253. swarm/static/rest_mode/svg/save.svg +0 -4
  254. swarm/static/rest_mode/svg/search.svg +0 -6
  255. swarm/static/rest_mode/svg/settings.svg +0 -4
  256. swarm/static/rest_mode/svg/speaker.svg +0 -5
  257. swarm/static/rest_mode/svg/stop.svg +0 -6
  258. swarm/static/rest_mode/svg/thumbs_down.svg +0 -3
  259. swarm/static/rest_mode/svg/thumbs_up.svg +0 -3
  260. swarm/static/rest_mode/svg/toggle_off.svg +0 -6
  261. swarm/static/rest_mode/svg/toggle_on.svg +0 -6
  262. swarm/static/rest_mode/svg/trash.svg +0 -10
  263. swarm/static/rest_mode/svg/undo.svg +0 -3
  264. swarm/static/rest_mode/svg/visible.svg +0 -8
  265. swarm/static/rest_mode/svg/voice.svg +0 -10
  266. swarm/templates/account/login.html +0 -22
  267. swarm/templates/account/signup.html +0 -32
  268. swarm/templates/base.html +0 -30
  269. swarm/templates/chat.html +0 -43
  270. swarm/templates/index.html +0 -35
  271. swarm/templates/rest_mode/components/chat_sidebar.html +0 -55
  272. swarm/templates/rest_mode/components/header.html +0 -45
  273. swarm/templates/rest_mode/components/main_chat_pane.html +0 -41
  274. swarm/templates/rest_mode/components/settings_dialog.html +0 -97
  275. swarm/templates/rest_mode/components/splash_screen.html +0 -7
  276. swarm/templates/rest_mode/components/top_bar.html +0 -28
  277. swarm/templates/rest_mode/message_ui.html +0 -50
  278. swarm/templates/rest_mode/slackbot.html +0 -30
  279. swarm/templates/simple_blueprint_page.html +0 -24
  280. swarm/templates/websocket_partials/final_system_message.html +0 -3
  281. swarm/templates/websocket_partials/system_message.html +0 -4
  282. swarm/templates/websocket_partials/user_message.html +0 -5
  283. swarm/utils/ansi_box.py +0 -34
  284. swarm/utils/disable_tracing.py +0 -38
  285. swarm/utils/log_utils.py +0 -63
  286. swarm/utils/openai_patch.py +0 -33
  287. swarm/ux/ansi_box.py +0 -43
  288. swarm/ux/spinner.py +0 -53
  289. {open_swarm-0.1.1745274976.dist-info → open_swarm-0.1.1748636259.dist-info}/licenses/LICENSE +0 -0
  290. /swarm/{core → extensions/blueprint}/blueprint_utils.py +0 -0
  291. /swarm/{core → extensions/blueprint}/common_utils.py +0 -0
  292. /swarm/{core → extensions/config}/setup_wizard.py +0 -0
  293. /swarm/{blueprints/rue_code → extensions/config/utils}/__init__.py +0 -0
  294. /swarm/{core → extensions/config}/utils/logger.py +0 -0
  295. /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())