open-swarm 0.1.1745275181__py3-none-any.whl → 0.1.1748636295__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (307) hide show
  1. open_swarm-0.1.1748636295.dist-info/METADATA +257 -0
  2. open_swarm-0.1.1748636295.dist-info/RECORD +89 -0
  3. {open_swarm-0.1.1745275181.dist-info → open_swarm-0.1.1748636295.dist-info}/WHEEL +2 -1
  4. open_swarm-0.1.1748636295.dist-info/entry_points.txt +3 -0
  5. open_swarm-0.1.1748636295.dist-info/top_level.txt +1 -0
  6. swarm/__init__.py +2 -0
  7. swarm/agent/agent.py +49 -0
  8. swarm/auth.py +48 -113
  9. swarm/consumers.py +0 -19
  10. swarm/core.py +411 -0
  11. swarm/extensions/blueprint/__init__.py +16 -30
  12. swarm/extensions/blueprint/agent_utils.py +45 -0
  13. swarm/extensions/blueprint/blueprint_base.py +562 -0
  14. swarm/extensions/blueprint/blueprint_discovery.py +112 -0
  15. swarm/extensions/blueprint/django_utils.py +79 -181
  16. swarm/extensions/blueprint/interactive_mode.py +72 -67
  17. swarm/extensions/blueprint/output_utils.py +82 -0
  18. swarm/{core → extensions/blueprint}/spinner.py +21 -30
  19. swarm/extensions/cli/cli_args.py +0 -6
  20. swarm/extensions/cli/commands/blueprint_management.py +9 -47
  21. swarm/extensions/cli/commands/config_management.py +6 -5
  22. swarm/extensions/cli/commands/edit_config.py +7 -16
  23. swarm/extensions/cli/commands/list_blueprints.py +1 -1
  24. swarm/extensions/cli/commands/validate_env.py +4 -11
  25. swarm/extensions/cli/commands/validate_envvars.py +6 -6
  26. swarm/extensions/cli/interactive_shell.py +2 -16
  27. swarm/extensions/config/config_loader.py +345 -107
  28. swarm/{core → extensions/config}/config_manager.py +38 -50
  29. swarm/{core → extensions/config}/server_config.py +0 -32
  30. swarm/extensions/launchers/build_launchers.py +14 -0
  31. swarm/{core → extensions/launchers}/build_swarm_wrapper.py +0 -0
  32. swarm/extensions/launchers/swarm_api.py +64 -8
  33. swarm/extensions/launchers/swarm_cli.py +300 -8
  34. swarm/extensions/mcp/__init__.py +1 -0
  35. swarm/extensions/mcp/cache_utils.py +32 -0
  36. swarm/extensions/mcp/mcp_client.py +233 -0
  37. swarm/extensions/mcp/mcp_tool_provider.py +135 -0
  38. swarm/extensions/mcp/mcp_utils.py +260 -0
  39. swarm/llm/chat_completion.py +166 -0
  40. swarm/serializers.py +5 -96
  41. swarm/settings.py +133 -85
  42. swarm/types.py +91 -0
  43. swarm/urls.py +74 -57
  44. swarm/utils/context_utils.py +4 -10
  45. swarm/utils/general_utils.py +0 -21
  46. swarm/utils/redact.py +36 -23
  47. swarm/views/api_views.py +39 -48
  48. swarm/views/chat_views.py +76 -236
  49. swarm/views/core_views.py +87 -80
  50. swarm/views/model_views.py +121 -64
  51. swarm/views/utils.py +439 -65
  52. swarm/views/web_views.py +2 -2
  53. open_swarm-0.1.1745275181.dist-info/METADATA +0 -874
  54. open_swarm-0.1.1745275181.dist-info/RECORD +0 -319
  55. open_swarm-0.1.1745275181.dist-info/entry_points.txt +0 -4
  56. swarm/blueprints/README.md +0 -68
  57. swarm/blueprints/blueprint_audit_status.json +0 -27
  58. swarm/blueprints/chatbot/README.md +0 -40
  59. swarm/blueprints/chatbot/blueprint_chatbot.py +0 -471
  60. swarm/blueprints/chatbot/metadata.json +0 -23
  61. swarm/blueprints/chatbot/templates/chatbot/chatbot.html +0 -33
  62. swarm/blueprints/chucks_angels/README.md +0 -11
  63. swarm/blueprints/chucks_angels/blueprint_chucks_angels.py +0 -7
  64. swarm/blueprints/chucks_angels/test_basic.py +0 -3
  65. swarm/blueprints/codey/CODEY.md +0 -15
  66. swarm/blueprints/codey/README.md +0 -115
  67. swarm/blueprints/codey/blueprint_codey.py +0 -1072
  68. swarm/blueprints/codey/codey_cli.py +0 -373
  69. swarm/blueprints/codey/instructions.md +0 -17
  70. swarm/blueprints/codey/metadata.json +0 -23
  71. swarm/blueprints/common/operation_box_utils.py +0 -83
  72. swarm/blueprints/digitalbutlers/README.md +0 -11
  73. swarm/blueprints/digitalbutlers/__init__.py +0 -1
  74. swarm/blueprints/digitalbutlers/blueprint_digitalbutlers.py +0 -7
  75. swarm/blueprints/digitalbutlers/test_basic.py +0 -3
  76. swarm/blueprints/divine_code/README.md +0 -3
  77. swarm/blueprints/divine_code/__init__.py +0 -10
  78. swarm/blueprints/divine_code/apps.py +0 -11
  79. swarm/blueprints/divine_code/blueprint_divine_code.py +0 -270
  80. swarm/blueprints/django_chat/apps.py +0 -6
  81. swarm/blueprints/django_chat/blueprint_django_chat.py +0 -268
  82. swarm/blueprints/django_chat/templates/django_chat/django_chat_webpage.html +0 -37
  83. swarm/blueprints/django_chat/urls.py +0 -8
  84. swarm/blueprints/django_chat/views.py +0 -32
  85. swarm/blueprints/echocraft/blueprint_echocraft.py +0 -384
  86. swarm/blueprints/flock/README.md +0 -11
  87. swarm/blueprints/flock/__init__.py +0 -8
  88. swarm/blueprints/flock/blueprint_flock.py +0 -7
  89. swarm/blueprints/flock/test_basic.py +0 -3
  90. swarm/blueprints/geese/README.md +0 -10
  91. swarm/blueprints/geese/__init__.py +0 -8
  92. swarm/blueprints/geese/blueprint_geese.py +0 -384
  93. swarm/blueprints/geese/geese_cli.py +0 -102
  94. swarm/blueprints/jeeves/README.md +0 -41
  95. swarm/blueprints/jeeves/blueprint_jeeves.py +0 -722
  96. swarm/blueprints/jeeves/jeeves_cli.py +0 -55
  97. swarm/blueprints/jeeves/metadata.json +0 -24
  98. swarm/blueprints/mcp_demo/blueprint_mcp_demo.py +0 -473
  99. swarm/blueprints/messenger/templates/messenger/messenger.html +0 -46
  100. swarm/blueprints/mission_improbable/blueprint_mission_improbable.py +0 -423
  101. swarm/blueprints/monkai_magic/blueprint_monkai_magic.py +0 -340
  102. swarm/blueprints/nebula_shellz/blueprint_nebula_shellz.py +0 -265
  103. swarm/blueprints/omniplex/blueprint_omniplex.py +0 -298
  104. swarm/blueprints/poets/blueprint_poets.py +0 -546
  105. swarm/blueprints/poets/poets_cli.py +0 -23
  106. swarm/blueprints/rue_code/README.md +0 -8
  107. swarm/blueprints/rue_code/blueprint_rue_code.py +0 -448
  108. swarm/blueprints/rue_code/rue_code_cli.py +0 -43
  109. swarm/blueprints/stewie/apps.py +0 -12
  110. swarm/blueprints/stewie/blueprint_family_ties.py +0 -349
  111. swarm/blueprints/stewie/models.py +0 -19
  112. swarm/blueprints/stewie/serializers.py +0 -10
  113. swarm/blueprints/stewie/settings.py +0 -17
  114. swarm/blueprints/stewie/urls.py +0 -11
  115. swarm/blueprints/stewie/views.py +0 -26
  116. swarm/blueprints/suggestion/blueprint_suggestion.py +0 -222
  117. swarm/blueprints/whinge_surf/README.md +0 -22
  118. swarm/blueprints/whinge_surf/__init__.py +0 -1
  119. swarm/blueprints/whinge_surf/blueprint_whinge_surf.py +0 -565
  120. swarm/blueprints/whinge_surf/whinge_surf_cli.py +0 -99
  121. swarm/blueprints/whiskeytango_foxtrot/__init__.py +0 -0
  122. swarm/blueprints/whiskeytango_foxtrot/apps.py +0 -11
  123. swarm/blueprints/whiskeytango_foxtrot/blueprint_whiskeytango_foxtrot.py +0 -339
  124. swarm/blueprints/zeus/__init__.py +0 -2
  125. swarm/blueprints/zeus/apps.py +0 -4
  126. swarm/blueprints/zeus/blueprint_zeus.py +0 -270
  127. swarm/blueprints/zeus/zeus_cli.py +0 -13
  128. swarm/cli/async_input.py +0 -65
  129. swarm/cli/async_input_demo.py +0 -32
  130. swarm/core/agent_utils.py +0 -21
  131. swarm/core/blueprint_base.py +0 -769
  132. swarm/core/blueprint_discovery.py +0 -125
  133. swarm/core/blueprint_runner.py +0 -59
  134. swarm/core/blueprint_ux.py +0 -109
  135. swarm/core/build_launchers.py +0 -15
  136. swarm/core/cli/__init__.py +0 -1
  137. swarm/core/cli/commands/__init__.py +0 -1
  138. swarm/core/cli/commands/blueprint_management.py +0 -7
  139. swarm/core/cli/interactive_shell.py +0 -14
  140. swarm/core/cli/main.py +0 -50
  141. swarm/core/cli/utils/__init__.py +0 -1
  142. swarm/core/cli/utils/discover_commands.py +0 -18
  143. swarm/core/config_loader.py +0 -122
  144. swarm/core/output_utils.py +0 -193
  145. swarm/core/session_logger.py +0 -42
  146. swarm/core/slash_commands.py +0 -89
  147. swarm/core/swarm_api.py +0 -68
  148. swarm/core/swarm_cli.py +0 -216
  149. swarm/core/utils/__init__.py +0 -0
  150. swarm/extensions/blueprint/cli_handler.py +0 -197
  151. swarm/extensions/blueprint/runnable_blueprint.py +0 -42
  152. swarm/extensions/cli/utils/__init__.py +0 -1
  153. swarm/extensions/cli/utils/async_input.py +0 -46
  154. swarm/extensions/cli/utils/prompt_user.py +0 -3
  155. swarm/management/__init__.py +0 -0
  156. swarm/management/commands/__init__.py +0 -0
  157. swarm/management/commands/runserver.py +0 -58
  158. swarm/middleware.py +0 -65
  159. swarm/permissions.py +0 -38
  160. swarm/static/contrib/fonts/fontawesome-webfont.ttf +0 -7
  161. swarm/static/contrib/fonts/fontawesome-webfont.woff +0 -7
  162. swarm/static/contrib/fonts/fontawesome-webfont.woff2 +0 -7
  163. swarm/static/contrib/markedjs/marked.min.js +0 -6
  164. swarm/static/contrib/tabler-icons/adjustments-horizontal.svg +0 -27
  165. swarm/static/contrib/tabler-icons/alert-triangle.svg +0 -21
  166. swarm/static/contrib/tabler-icons/archive.svg +0 -21
  167. swarm/static/contrib/tabler-icons/artboard.svg +0 -27
  168. swarm/static/contrib/tabler-icons/automatic-gearbox.svg +0 -23
  169. swarm/static/contrib/tabler-icons/box-multiple.svg +0 -19
  170. swarm/static/contrib/tabler-icons/carambola.svg +0 -19
  171. swarm/static/contrib/tabler-icons/copy.svg +0 -20
  172. swarm/static/contrib/tabler-icons/download.svg +0 -21
  173. swarm/static/contrib/tabler-icons/edit.svg +0 -21
  174. swarm/static/contrib/tabler-icons/filled/carambola.svg +0 -13
  175. swarm/static/contrib/tabler-icons/filled/paint.svg +0 -13
  176. swarm/static/contrib/tabler-icons/headset.svg +0 -22
  177. swarm/static/contrib/tabler-icons/layout-sidebar-left-collapse.svg +0 -21
  178. swarm/static/contrib/tabler-icons/layout-sidebar-left-expand.svg +0 -21
  179. swarm/static/contrib/tabler-icons/layout-sidebar-right-collapse.svg +0 -21
  180. swarm/static/contrib/tabler-icons/layout-sidebar-right-expand.svg +0 -21
  181. swarm/static/contrib/tabler-icons/message-chatbot.svg +0 -22
  182. swarm/static/contrib/tabler-icons/message-star.svg +0 -22
  183. swarm/static/contrib/tabler-icons/message-x.svg +0 -23
  184. swarm/static/contrib/tabler-icons/message.svg +0 -21
  185. swarm/static/contrib/tabler-icons/paperclip.svg +0 -18
  186. swarm/static/contrib/tabler-icons/playlist-add.svg +0 -22
  187. swarm/static/contrib/tabler-icons/robot.svg +0 -26
  188. swarm/static/contrib/tabler-icons/search.svg +0 -19
  189. swarm/static/contrib/tabler-icons/settings.svg +0 -20
  190. swarm/static/contrib/tabler-icons/thumb-down.svg +0 -19
  191. swarm/static/contrib/tabler-icons/thumb-up.svg +0 -19
  192. swarm/static/css/dropdown.css +0 -22
  193. swarm/static/htmx/htmx.min.js +0 -0
  194. swarm/static/js/dropdown.js +0 -23
  195. swarm/static/rest_mode/css/base.css +0 -470
  196. swarm/static/rest_mode/css/chat-history.css +0 -286
  197. swarm/static/rest_mode/css/chat.css +0 -251
  198. swarm/static/rest_mode/css/chatbot.css +0 -74
  199. swarm/static/rest_mode/css/chatgpt.css +0 -62
  200. swarm/static/rest_mode/css/colors/corporate.css +0 -74
  201. swarm/static/rest_mode/css/colors/pastel.css +0 -81
  202. swarm/static/rest_mode/css/colors/tropical.css +0 -82
  203. swarm/static/rest_mode/css/general.css +0 -142
  204. swarm/static/rest_mode/css/layout.css +0 -167
  205. swarm/static/rest_mode/css/layouts/messenger-layout.css +0 -17
  206. swarm/static/rest_mode/css/layouts/minimalist-layout.css +0 -57
  207. swarm/static/rest_mode/css/layouts/mobile-layout.css +0 -8
  208. swarm/static/rest_mode/css/messages.css +0 -84
  209. swarm/static/rest_mode/css/messenger.css +0 -135
  210. swarm/static/rest_mode/css/settings.css +0 -91
  211. swarm/static/rest_mode/css/simple.css +0 -44
  212. swarm/static/rest_mode/css/slack.css +0 -58
  213. swarm/static/rest_mode/css/style.css +0 -156
  214. swarm/static/rest_mode/css/theme.css +0 -30
  215. swarm/static/rest_mode/css/toast.css +0 -40
  216. swarm/static/rest_mode/js/auth.js +0 -9
  217. swarm/static/rest_mode/js/blueprint.js +0 -41
  218. swarm/static/rest_mode/js/blueprintUtils.js +0 -12
  219. swarm/static/rest_mode/js/chatLogic.js +0 -79
  220. swarm/static/rest_mode/js/debug.js +0 -63
  221. swarm/static/rest_mode/js/events.js +0 -98
  222. swarm/static/rest_mode/js/main.js +0 -19
  223. swarm/static/rest_mode/js/messages.js +0 -264
  224. swarm/static/rest_mode/js/messengerLogic.js +0 -355
  225. swarm/static/rest_mode/js/modules/apiService.js +0 -84
  226. swarm/static/rest_mode/js/modules/blueprintManager.js +0 -162
  227. swarm/static/rest_mode/js/modules/chatHistory.js +0 -110
  228. swarm/static/rest_mode/js/modules/debugLogger.js +0 -14
  229. swarm/static/rest_mode/js/modules/eventHandlers.js +0 -107
  230. swarm/static/rest_mode/js/modules/messageProcessor.js +0 -120
  231. swarm/static/rest_mode/js/modules/state.js +0 -7
  232. swarm/static/rest_mode/js/modules/userInteractions.js +0 -29
  233. swarm/static/rest_mode/js/modules/validation.js +0 -23
  234. swarm/static/rest_mode/js/rendering.js +0 -119
  235. swarm/static/rest_mode/js/settings.js +0 -130
  236. swarm/static/rest_mode/js/sidebar.js +0 -94
  237. swarm/static/rest_mode/js/simpleLogic.js +0 -37
  238. swarm/static/rest_mode/js/slackLogic.js +0 -66
  239. swarm/static/rest_mode/js/splash.js +0 -76
  240. swarm/static/rest_mode/js/theme.js +0 -111
  241. swarm/static/rest_mode/js/toast.js +0 -36
  242. swarm/static/rest_mode/js/ui.js +0 -265
  243. swarm/static/rest_mode/js/validation.js +0 -57
  244. swarm/static/rest_mode/svg/animated_spinner.svg +0 -12
  245. swarm/static/rest_mode/svg/arrow_down.svg +0 -5
  246. swarm/static/rest_mode/svg/arrow_left.svg +0 -5
  247. swarm/static/rest_mode/svg/arrow_right.svg +0 -5
  248. swarm/static/rest_mode/svg/arrow_up.svg +0 -5
  249. swarm/static/rest_mode/svg/attach.svg +0 -8
  250. swarm/static/rest_mode/svg/avatar.svg +0 -7
  251. swarm/static/rest_mode/svg/canvas.svg +0 -6
  252. swarm/static/rest_mode/svg/chat_history.svg +0 -4
  253. swarm/static/rest_mode/svg/close.svg +0 -5
  254. swarm/static/rest_mode/svg/copy.svg +0 -4
  255. swarm/static/rest_mode/svg/dark_mode.svg +0 -3
  256. swarm/static/rest_mode/svg/edit.svg +0 -5
  257. swarm/static/rest_mode/svg/layout.svg +0 -9
  258. swarm/static/rest_mode/svg/logo.svg +0 -29
  259. swarm/static/rest_mode/svg/logout.svg +0 -5
  260. swarm/static/rest_mode/svg/mobile.svg +0 -5
  261. swarm/static/rest_mode/svg/new_chat.svg +0 -4
  262. swarm/static/rest_mode/svg/not_visible.svg +0 -5
  263. swarm/static/rest_mode/svg/plus.svg +0 -7
  264. swarm/static/rest_mode/svg/run_code.svg +0 -6
  265. swarm/static/rest_mode/svg/save.svg +0 -4
  266. swarm/static/rest_mode/svg/search.svg +0 -6
  267. swarm/static/rest_mode/svg/settings.svg +0 -4
  268. swarm/static/rest_mode/svg/speaker.svg +0 -5
  269. swarm/static/rest_mode/svg/stop.svg +0 -6
  270. swarm/static/rest_mode/svg/thumbs_down.svg +0 -3
  271. swarm/static/rest_mode/svg/thumbs_up.svg +0 -3
  272. swarm/static/rest_mode/svg/toggle_off.svg +0 -6
  273. swarm/static/rest_mode/svg/toggle_on.svg +0 -6
  274. swarm/static/rest_mode/svg/trash.svg +0 -10
  275. swarm/static/rest_mode/svg/undo.svg +0 -3
  276. swarm/static/rest_mode/svg/visible.svg +0 -8
  277. swarm/static/rest_mode/svg/voice.svg +0 -10
  278. swarm/templates/account/login.html +0 -22
  279. swarm/templates/account/signup.html +0 -32
  280. swarm/templates/base.html +0 -30
  281. swarm/templates/chat.html +0 -43
  282. swarm/templates/index.html +0 -35
  283. swarm/templates/rest_mode/components/chat_sidebar.html +0 -55
  284. swarm/templates/rest_mode/components/header.html +0 -45
  285. swarm/templates/rest_mode/components/main_chat_pane.html +0 -41
  286. swarm/templates/rest_mode/components/settings_dialog.html +0 -97
  287. swarm/templates/rest_mode/components/splash_screen.html +0 -7
  288. swarm/templates/rest_mode/components/top_bar.html +0 -28
  289. swarm/templates/rest_mode/message_ui.html +0 -50
  290. swarm/templates/rest_mode/slackbot.html +0 -30
  291. swarm/templates/simple_blueprint_page.html +0 -24
  292. swarm/templates/websocket_partials/final_system_message.html +0 -3
  293. swarm/templates/websocket_partials/system_message.html +0 -4
  294. swarm/templates/websocket_partials/user_message.html +0 -5
  295. swarm/utils/ansi_box.py +0 -34
  296. swarm/utils/disable_tracing.py +0 -38
  297. swarm/utils/log_utils.py +0 -63
  298. swarm/utils/openai_patch.py +0 -33
  299. swarm/ux/ansi_box.py +0 -43
  300. swarm/ux/spinner.py +0 -53
  301. {open_swarm-0.1.1745275181.dist-info → open_swarm-0.1.1748636295.dist-info}/licenses/LICENSE +0 -0
  302. /swarm/{core → extensions/blueprint}/blueprint_utils.py +0 -0
  303. /swarm/{core → extensions/blueprint}/common_utils.py +0 -0
  304. /swarm/{core → extensions/config}/setup_wizard.py +0 -0
  305. /swarm/{blueprints/rue_code → extensions/config/utils}/__init__.py +0 -0
  306. /swarm/{core → extensions/config}/utils/logger.py +0 -0
  307. /swarm/{core → extensions/launchers}/swarm_wrapper.py +0 -0
@@ -1,423 +0,0 @@
1
- """
2
- MissionImprobable Blueprint
3
-
4
- Viral docstring update: Operational as of 2025-04-18T10:14:18Z (UTC).
5
- Self-healing, fileops-enabled, swarm-scalable.
6
- """
7
- import logging
8
- import os
9
- import sys
10
- import json
11
- import sqlite3 # Use standard sqlite3 module
12
- from pathlib import Path
13
- from typing import Dict, Any, List, ClassVar, Optional
14
- from datetime import datetime
15
- import pytz
16
-
17
- # Last swarm update: 2025-04-18T10:15:21Z (UTC)
18
-
19
- # Ensure src is in path for BlueprintBase import
20
- project_root = os.path.abspath(os.path.join(os.path.dirname(__file__), '..', '..'))
21
- src_path = os.path.join(project_root, 'src')
22
- if src_path not in sys.path: sys.path.insert(0, src_path)
23
-
24
- try:
25
- from agents import Agent, Tool, function_tool, Runner
26
- from agents.mcp import MCPServer
27
- from agents.models.interface import Model
28
- from agents.models.openai_chatcompletions import OpenAIChatCompletionsModel
29
- from openai import AsyncOpenAI
30
- from swarm.core.blueprint_base import BlueprintBase
31
- from swarm.core.blueprint_ux import BlueprintUXImproved
32
- except ImportError as e:
33
- print(f"ERROR: Import failed in MissionImprobableBlueprint: {e}. Check dependencies.")
34
- print(f"sys.path: {sys.path}")
35
- sys.exit(1)
36
-
37
- logger = logging.getLogger(__name__)
38
-
39
- # Patch: Expose underlying fileops functions for direct testing
40
- class PatchedFunctionTool:
41
- def __init__(self, func, name):
42
- self.func = func
43
- self.name = name
44
-
45
- def read_file(path: str) -> str:
46
- try:
47
- with open(path, 'r') as f:
48
- return f.read()
49
- except Exception as e:
50
- return f"ERROR: {e}"
51
- def write_file(path: str, content: str) -> str:
52
- try:
53
- with open(path, 'w') as f:
54
- f.write(content)
55
- return "OK: file written"
56
- except Exception as e:
57
- return f"ERROR: {e}"
58
- def list_files(directory: str = '.') -> str:
59
- try:
60
- return '\n'.join(os.listdir(directory))
61
- except Exception as e:
62
- return f"ERROR: {e}"
63
- def execute_shell_command(command: str) -> str:
64
- """
65
- Executes a shell command and returns its stdout and stderr.
66
- Timeout is configurable via SWARM_COMMAND_TIMEOUT (default: 60s).
67
- """
68
- logger.info(f"Executing shell command: {command}")
69
- try:
70
- import os
71
- timeout = int(os.getenv("SWARM_COMMAND_TIMEOUT", "60"))
72
- result = subprocess.run(command, shell=True, capture_output=True, text=True, timeout=timeout)
73
- output = f"Exit Code: {result.returncode}\n"
74
- if result.stdout:
75
- output += f"STDOUT:\n{result.stdout}\n"
76
- if result.stderr:
77
- output += f"STDERR:\n{result.stderr}\n"
78
- logger.info(f"Command finished. Exit Code: {result.returncode}")
79
- return output.strip()
80
- except subprocess.TimeoutExpired:
81
- logger.error(f"Command timed out: {command}")
82
- return f"Error: Command timed out after {os.getenv('SWARM_COMMAND_TIMEOUT', '60')} seconds."
83
- except Exception as e:
84
- logger.error(f"Error executing command '{command}': {e}", exc_info=True)
85
- return f"Error executing command: {e}"
86
- read_file_tool = PatchedFunctionTool(read_file, 'read_file')
87
- write_file_tool = PatchedFunctionTool(write_file, 'write_file')
88
- list_files_tool = PatchedFunctionTool(list_files, 'list_files')
89
- execute_shell_command_tool = PatchedFunctionTool(execute_shell_command, 'execute_shell_command')
90
-
91
- # --- Database Constants ---
92
- # Using the same DB file as dilbot_universe
93
- DB_FILE_NAME = "swarm_instructions.db"
94
- DB_PATH = Path(project_root) / DB_FILE_NAME
95
- TABLE_NAME = "agent_instructions" # agent_name TEXT PRIMARY KEY, instruction_text TEXT, model_profile TEXT
96
-
97
- # Spinner UX enhancement (Open Swarm TODO)
98
- SPINNER_STATES = ['Generating.', 'Generating..', 'Generating...', 'Running...']
99
-
100
- # --- Define the Blueprint ---
101
- # Renamed class for consistency
102
- class MissionImprobableBlueprint(BlueprintBase):
103
- """A cheeky team on a mission: led by JimFlimsy with support from CinnamonToast and RollinFumble."""
104
- metadata: ClassVar[Dict[str, Any]] = {
105
- "name": "MissionImprobableBlueprint",
106
- "title": "Mission: Improbable",
107
- "description": "A cheeky team led by JimFlimsy (coordinator), CinnamonToast (strategist/filesystem), and RollinFumble (operative/shell). Uses SQLite for instructions.",
108
- "version": "1.1.0", # Refactored version
109
- "author": "Open Swarm Team (Refactored)",
110
- "tags": ["comedy", "multi-agent", "filesystem", "shell", "sqlite"],
111
- "required_mcp_servers": ["memory", "filesystem", "mcp-shell"], # Servers needed by the agents
112
- "env_vars": ["ALLOWED_PATH"], # Informational: filesystem MCP likely needs this
113
- }
114
-
115
- # Caches
116
- _openai_client_cache: Dict[str, AsyncOpenAI] = {}
117
- _model_instance_cache: Dict[str, Model] = {}
118
- _db_initialized = False # Flag to ensure DB init runs only once per instance
119
-
120
- def __init__(self, blueprint_id: str = "mission_improbable", config=None, config_path=None, **kwargs):
121
- super().__init__(blueprint_id, config=config, config_path=config_path, **kwargs)
122
- self.blueprint_id = blueprint_id
123
- self.config_path = config_path
124
- self._config = config if config is not None else None
125
- self._llm_profile_name = None
126
- self._llm_profile_data = None
127
- self._markdown_output = None
128
- # Add other attributes as needed for MissionImprobable
129
- # ...
130
-
131
- # --- Database Interaction ---
132
- def _init_db_and_load_data(self) -> None:
133
- """Initializes the SQLite DB, creates table, and loads sample data if needed."""
134
- """Initializes the SQLite DB file and loads sample instruction for JimFlimsy."""
135
- if self._db_initialized:
136
- return
137
- # Create parent directory if needed
138
- try:
139
- DB_PATH.parent.mkdir(parents=True, exist_ok=True)
140
- # Create or open the database file
141
- with open(DB_PATH, 'a'):
142
- pass
143
- # Initialize DB and table
144
- conn = sqlite3.connect(str(DB_PATH))
145
- cursor = conn.cursor()
146
- cursor.execute(f"CREATE TABLE IF NOT EXISTS {TABLE_NAME} (agent_name TEXT PRIMARY KEY, instruction_text TEXT NOT NULL, model_profile TEXT DEFAULT 'default')")
147
- # Load sample data for JimFlimsy if not present
148
- cursor.execute("SELECT COUNT(*) FROM " + TABLE_NAME + " WHERE agent_name = ?", ("JimFlimsy",))
149
- count = cursor.fetchone()[0]
150
- if count == 0:
151
- cursor.execute(
152
- "INSERT OR IGNORE INTO " + TABLE_NAME + " (agent_name, instruction_text, model_profile) VALUES (?, ?, ?)",
153
- ("JimFlimsy", "You’re JimFlimsy, the fearless leader.", "default")
154
- )
155
- conn.commit()
156
- conn.close()
157
- self._db_initialized = True
158
- except Exception as e:
159
- logger.error(f"Error during DB initialization/loading: {e}", exc_info=True)
160
- self._db_initialized = False
161
-
162
- def get_agent_config(self, agent_name: str) -> Dict[str, Any]:
163
- """Fetches agent config from SQLite DB or returns defaults."""
164
- if self._db_initialized:
165
- try:
166
- with sqlite3.connect(DB_PATH) as conn:
167
- conn.row_factory = sqlite3.Row
168
- cursor = conn.cursor()
169
- cursor.execute(f"SELECT instruction_text, model_profile FROM {TABLE_NAME} WHERE agent_name = ?", (agent_name,))
170
- row = cursor.fetchone()
171
- if row:
172
- logger.debug(f"Loaded config for agent '{agent_name}' from SQLite.")
173
- return {"instructions": row["instruction_text"], "model_profile": row["model_profile"] or "default"}
174
- else:
175
- logger.warning(f"No config found for agent '{agent_name}' in SQLite. Using defaults.")
176
- except sqlite3.Error as e:
177
- logger.error(f"SQLite error fetching config for '{agent_name}': {e}. Using defaults.", exc_info=True)
178
- except Exception as e:
179
- logger.error(f"Unexpected error fetching config for '{agent_name}': {e}. Using defaults.", exc_info=True)
180
-
181
- # --- Fallback Hardcoded Defaults ---
182
- logger.warning(f"Using hardcoded default config for agent '{agent_name}'.")
183
- default_instructions = {
184
- "JimFlimsy": "You are JimFlimsy, the leader. Delegate tasks. [Default - DB Failed]",
185
- "CinnamonToast": "You are CinnamonToast, strategist. Use filesystem. [Default - DB Failed]",
186
- "RollinFumble": "You are RollinFumble, operative. Use shell. [Default - DB Failed]",
187
- }
188
- return {
189
- "instructions": default_instructions.get(agent_name, f"Default instructions for {agent_name}."),
190
- "model_profile": "default",
191
- }
192
-
193
- # --- Model Instantiation Helper --- (Standard helper)
194
- def _get_model_instance(self, profile_name: str) -> Model:
195
- """Retrieves or creates an LLM Model instance."""
196
- # ... (Implementation is the same as previous refactors) ...
197
- if profile_name in self._model_instance_cache:
198
- logger.debug(f"Using cached Model instance for profile '{profile_name}'.")
199
- return self._model_instance_cache[profile_name]
200
- logger.debug(f"Creating new Model instance for profile '{profile_name}'.")
201
- profile_data = self.get_llm_profile(profile_name)
202
- if not profile_data:
203
- logger.critical(f"LLM profile '{profile_name}' (or 'default') not found.")
204
- raise ValueError(f"Missing LLM profile configuration for '{profile_name}' or 'default'.")
205
- provider = profile_data.get("provider", "openai").lower()
206
- model_name = profile_data.get("model")
207
- if not model_name:
208
- logger.critical(f"LLM profile '{profile_name}' missing 'model' key.")
209
- raise ValueError(f"Missing 'model' key in LLM profile '{profile_name}'.")
210
- if provider != "openai":
211
- logger.error(f"Unsupported LLM provider '{provider}'.")
212
- raise ValueError(f"Unsupported LLM provider: {provider}")
213
- client_cache_key = f"{provider}_{profile_data.get('base_url')}"
214
- if client_cache_key not in self._openai_client_cache:
215
- client_kwargs = { "api_key": profile_data.get("api_key"), "base_url": profile_data.get("base_url") }
216
- filtered_kwargs = {k: v for k, v in client_kwargs.items() if v is not None}
217
- log_kwargs = {k:v for k,v in filtered_kwargs.items() if k != 'api_key'}
218
- logger.debug(f"Creating new AsyncOpenAI client for '{profile_name}': {log_kwargs}")
219
- try: self._openai_client_cache[client_cache_key] = AsyncOpenAI(**filtered_kwargs)
220
- except Exception as e: raise ValueError(f"Failed to init OpenAI client: {e}") from e
221
- client = self._openai_client_cache[client_cache_key]
222
- logger.debug(f"Instantiating OpenAIChatCompletionsModel(model='{model_name}') for '{profile_name}'.")
223
- try:
224
- model_instance = OpenAIChatCompletionsModel(model=model_name, openai_client=client)
225
- self._model_instance_cache[profile_name] = model_instance
226
- return model_instance
227
- except Exception as e: raise ValueError(f"Failed to init LLM provider: {e}") from e
228
-
229
- # --- Agent Creation ---
230
- def create_starting_agent(self, mcp_servers: List[MCPServer]) -> Agent:
231
- """Creates the Mission Improbable agent team and returns JimFlimsy (Coordinator)."""
232
- # Initialize DB and load data if needed
233
- self._init_db_and_load_data()
234
-
235
- logger.debug("Creating Mission Improbable agent team...")
236
- self._model_instance_cache = {}
237
- self._openai_client_cache = {}
238
-
239
- # Helper to filter MCP servers
240
- def get_agent_mcps(names: List[str]) -> List[MCPServer]:
241
- return [s for s in mcp_servers if s.name in names]
242
-
243
- # Create agents, fetching config and assigning MCPs
244
- agents: Dict[str, Agent] = {}
245
- for name in ["JimFlimsy", "CinnamonToast", "RollinFumble"]:
246
- config = self.get_agent_config(name)
247
- model_instance = self._get_model_instance(config["model_profile"])
248
- agent_mcps = []
249
- if name == "JimFlimsy": agent_mcps = get_agent_mcps(["memory"])
250
- elif name == "CinnamonToast": agent_mcps = get_agent_mcps(["filesystem"])
251
- elif name == "RollinFumble": agent_mcps = get_agent_mcps(["mcp-shell"])
252
-
253
- agents[name] = Agent(
254
- name=name,
255
- instructions=config["instructions"] + "\nYou can use fileops tools (read_file, write_file, list_files, execute_shell_command) for any file or shell tasks.",
256
- model=model_instance,
257
- tools=[read_file_tool, write_file_tool, list_files_tool, execute_shell_command_tool],
258
- mcp_servers=agent_mcps
259
- )
260
-
261
- # Add agent tools to the coordinator (JimFlimsy)
262
- agents["JimFlimsy"].tools.extend([
263
- agents["CinnamonToast"].as_tool(tool_name="CinnamonToast", tool_description="Delegate file management or strategic planning tasks."),
264
- agents["RollinFumble"].as_tool(tool_name="RollinFumble", tool_description="Delegate shell command execution tasks.")
265
- ])
266
-
267
- logger.debug("Mission Improbable agents created. Starting with JimFlimsy.")
268
- return agents["JimFlimsy"] # Jim is the coordinator
269
-
270
- async def run(self, messages: list, **kwargs):
271
- """Main execution entry point for the MissionImprobable blueprint."""
272
- logger.info("MissionImprobableBlueprint run method called.")
273
- instruction = messages[-1].get("content", "") if messages else ""
274
- from agents import Runner
275
- ux = BlueprintUXImproved(style="serious")
276
- spinner_idx = 0
277
- start_time = time.time()
278
- spinner_yield_interval = 1.0 # seconds
279
- last_spinner_time = start_time
280
- yielded_spinner = False
281
- result_chunks = []
282
- try:
283
- runner_gen = Runner.run(self.create_starting_agent([]), instruction)
284
- while True:
285
- now = time.time()
286
- try:
287
- chunk = next(runner_gen)
288
- result_chunks.append(chunk)
289
- # If chunk is a final result, wrap and yield
290
- if chunk and isinstance(chunk, dict) and "messages" in chunk:
291
- content = chunk["messages"][0]["content"] if chunk["messages"] else ""
292
- summary = ux.summary("Operation", len(result_chunks), {"instruction": instruction[:40]})
293
- box = ux.ansi_emoji_box(
294
- title="MissionImprobable Result",
295
- content=content,
296
- summary=summary,
297
- params={"instruction": instruction[:40]},
298
- result_count=len(result_chunks),
299
- op_type="run",
300
- status="success"
301
- )
302
- yield {"messages": [{"role": "assistant", "content": box}]}
303
- else:
304
- yield chunk
305
- yielded_spinner = False
306
- except StopIteration:
307
- break
308
- except Exception:
309
- if now - last_spinner_time >= spinner_yield_interval:
310
- taking_long = (now - start_time > 10)
311
- spinner_msg = ux.spinner(spinner_idx, taking_long=taking_long)
312
- yield {"messages": [{"role": "assistant", "content": spinner_msg}]}
313
- spinner_idx += 1
314
- last_spinner_time = now
315
- yielded_spinner = True
316
- if not result_chunks and not yielded_spinner:
317
- yield {"messages": [{"role": "assistant", "content": ux.spinner(0)}]}
318
- except Exception as e:
319
- logger.error(f"Error during MissionImprobable run: {e}", exc_info=True)
320
- yield {"messages": [{"role": "assistant", "content": f"An error occurred: {e}"}]}
321
-
322
- # --- Spinner and ANSI/emoji operation box for unified UX (for CLI/dev runs) ---
323
- from swarm.ux.ansi_box import ansi_box
324
- from rich.console import Console
325
- from rich.style import Style
326
- from rich.text import Text
327
- import threading
328
- import time
329
-
330
- class MissionImprobableSpinner:
331
- FRAMES = [
332
- "Generating.", "Generating..", "Generating...", "Running...",
333
- "⠋ Generating...", "⠙ Generating...", "⠹ Generating...", "⠸ Generating...",
334
- "⠼ Generating...", "⠴ Generating...", "⠦ Generating...", "⠧ Generating...",
335
- "⠇ Generating...", "⠏ Generating...", "🤖 Generating...", "💡 Generating...", "✨ Generating..."
336
- ]
337
- SLOW_FRAME = "Generating... Taking longer than expected"
338
- INTERVAL = 0.12
339
- SLOW_THRESHOLD = 10 # seconds
340
-
341
- def __init__(self):
342
- self._stop_event = threading.Event()
343
- self._thread = None
344
- self._start_time = None
345
- self.console = Console()
346
- self._last_frame = None
347
- self._last_slow = False
348
-
349
- def start(self):
350
- self._stop_event.clear()
351
- self._start_time = time.time()
352
- self._thread = threading.Thread(target=self._spin, daemon=True)
353
- self._thread.start()
354
-
355
- def _spin(self):
356
- idx = 0
357
- while not self._stop_event.is_set():
358
- elapsed = time.time() - self._start_time
359
- if elapsed > self.SLOW_THRESHOLD:
360
- txt = Text(self.SLOW_FRAME, style=Style(color="yellow", bold=True))
361
- self._last_frame = self.SLOW_FRAME
362
- self._last_slow = True
363
- else:
364
- frame = self.FRAMES[idx % len(self.FRAMES)]
365
- txt = Text(frame, style=Style(color="cyan", bold=True))
366
- self._last_frame = frame
367
- self._last_slow = False
368
- self.console.print(txt, end="\r", soft_wrap=True, highlight=False)
369
- time.sleep(self.INTERVAL)
370
- idx += 1
371
- self.console.print(" " * 40, end="\r") # Clear line
372
-
373
- def stop(self, final_message="Done!"):
374
- self._stop_event.set()
375
- if self._thread:
376
- self._thread.join()
377
- self.console.print(Text(final_message, style=Style(color="green", bold=True)))
378
-
379
- def current_spinner_state(self):
380
- if self._last_slow:
381
- return self.SLOW_FRAME
382
- return self._last_frame or self.FRAMES[0]
383
-
384
-
385
- def print_operation_box(op_type, results, params=None, result_type="mission", taking_long=False):
386
- emoji = "🕵️" if result_type == "mission" else "🔍"
387
- style = 'success' if result_type == "mission" else 'default'
388
- box_title = op_type if op_type else ("MissionImprobable Output" if result_type == "mission" else "Results")
389
- summary_lines = []
390
- count = len(results) if isinstance(results, list) else 0
391
- summary_lines.append(f"Results: {count}")
392
- if params:
393
- for k, v in params.items():
394
- summary_lines.append(f"{k.capitalize()}: {v}")
395
- box_content = "\n".join(summary_lines + ["\n".join(map(str, results))])
396
- ansi_box(box_title, box_content, count=count, params=params, style=style if not taking_long else 'warning', emoji=emoji)
397
-
398
- # Standard Python entry point
399
- if __name__ == "__main__":
400
- import asyncio
401
- import json
402
- print("\033[1;36m\n╔══════════════════════════════════════════════════════════════╗\n║ 🕵️ MISSION IMPROBABLE: SWARM STRATEGY & TASK DEMO ║\n╠══════════════════════════════════════════════════════════════╣\n║ This blueprint demonstrates viral swarm propagation, ║\n║ strategic task planning, and agent collaboration. ║\n║ Try running: python blueprint_mission_improbable.py ║\n╚══════════════════════════════════════════════════════════════╝\033[0m")
403
- messages = [
404
- {"role": "user", "content": "Show me how Mission Improbable plans tasks and leverages swarm strategy."}
405
- ]
406
- blueprint = MissionImprobableBlueprint(blueprint_id="demo-1")
407
- async def run_and_print():
408
- spinner = MissionImprobableSpinner()
409
- spinner.start()
410
- try:
411
- all_results = []
412
- async for response in blueprint.run(messages):
413
- content = response["messages"][0]["content"]
414
- all_results.append(content)
415
- finally:
416
- spinner.stop()
417
- print_operation_box(
418
- op_type="MissionImprobable Output",
419
- results=all_results,
420
- params={"prompt": messages[0]["content"]},
421
- result_type="mission"
422
- )
423
- asyncio.run(run_and_print())