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
@@ -3,10 +3,12 @@ Interactive mode logic for blueprint extensions.
3
3
  """
4
4
 
5
5
  import logging
6
- from typing import List, Dict, Any # Added Any
6
+ from typing import List, Dict
7
7
 
8
8
  # Import the standalone output function
9
9
  from .output_utils import pretty_print_response
10
+ # Assuming spinner is managed by the blueprint instance passed in
11
+ # from .spinner import Spinner # Not needed directly here
10
12
 
11
13
  logger = logging.getLogger(__name__)
12
14
 
@@ -14,32 +16,24 @@ def run_interactive_mode(blueprint, stream: bool = False) -> None:
14
16
  """
15
17
  Run the interactive mode for a blueprint instance.
16
18
 
17
- This function implements the interactive loop where the user is
18
- prompted for input,
19
- and responses are generated and printed using the blueprint inst
20
- ance's methods.
19
+ This function implements the interactive loop where the user is prompted for input,
20
+ and responses are generated and printed using the blueprint instance's methods.
21
21
  """
22
22
  logger.debug("Starting interactive mode.")
23
- if not blueprint.starting_agent:
23
+ if not blueprint.starting_agent or not blueprint.swarm:
24
24
  logger.error("Starting agent or Swarm not initialized.")
25
- # --- FIX: Terminate string literal correctly ---
26
25
  raise ValueError("Starting agent and Swarm must be initialized.")
27
- # --- End FIX ---
28
-
29
26
  print("Blueprint Interactive Mode 🐝")
30
- messages: List[Dict[str, Any]] = []
27
+ messages: List[Dict[str, str]] = []
31
28
  first_input = True
32
29
  message_count = 0
33
30
  while True:
31
+ # Use the blueprint's spinner instance if it exists
34
32
  spinner = getattr(blueprint, 'spinner', None)
35
- if spinner: spinner.stop()
36
-
37
- try:
38
- user_input = input(blueprint.prompt).strip()
39
- except (EOFError, KeyboardInterrupt):
40
- print("\nExiting interactive mode.")
41
- break
33
+ if spinner:
34
+ spinner.stop()
42
35
 
36
+ user_input = input(blueprint.prompt).strip()
43
37
  if user_input.lower() in {"exit", "quit", "/quit"}:
44
38
  print("Exiting interactive mode.")
45
39
  break
@@ -49,54 +43,65 @@ ance's methods.
49
43
  messages.append({"role": "user", "content": user_input})
50
44
  message_count += 1
51
45
 
52
- try:
53
- result = blueprint.run_with_context(messages, blueprint.context_variables)
54
- swarm_response = result.get("response")
55
- blueprint.context_variables = result.get("context_variables", blueprint.context_variables)
56
-
57
- response_messages_objects = []
58
- if hasattr(swarm_response, 'messages'):
59
- response_messages_objects = swarm_response.messages
60
- elif isinstance(swarm_response, dict) and 'messages' in swarm_response:
61
- raw_msgs = swarm_response.get('messages', [])
62
- if raw_msgs and not isinstance(raw_msgs[0], dict):
63
- try: response_messages_objects = raw_msgs
64
- except Exception: logger.error("Failed to process messages from dict response."); response_messages_objects = []
65
- else: response_messages_objects = raw_msgs
66
-
67
- response_messages_dicts = []
68
- if response_messages_objects:
69
- try:
70
- response_messages_dicts = [
71
- msg.model_dump(exclude_none=True) if hasattr(msg, 'model_dump') else msg
72
- for msg in response_messages_objects
73
- ]
74
- except Exception as e:
75
- logger.error(f"Failed to dump response messages to dict: {e}")
76
- response_messages_dicts = [{"role": "system", "content": "[Error displaying response]"}]
77
-
78
- if stream:
79
- logger.warning("Streaming not fully supported in this interactive mode version.")
80
- pretty_print_response(messages=response_messages_dicts, use_markdown=getattr(blueprint, 'use_markdown', False), spinner=spinner)
81
- else:
82
- pretty_print_response(messages=response_messages_dicts, use_markdown=getattr(blueprint, 'use_markdown', False), spinner=spinner)
83
-
84
- messages.extend(response_messages_dicts)
85
-
86
- if getattr(blueprint, 'update_user_goal', False) and \
87
- (message_count - getattr(blueprint, 'last_goal_update_count', 0)) >= \
88
- getattr(blueprint, 'update_user_goal_frequency', 5):
89
- try:
90
- import asyncio
91
- asyncio.run(blueprint._update_user_goal_async(messages))
92
- blueprint.last_goal_update_count = message_count
93
- except AttributeError: logger.warning("Blueprint missing '_update_user_goal_async'.")
94
- except Exception as e: logger.error(f"Error updating goal: {e}", exc_info=True)
95
-
96
- if getattr(blueprint, 'auto_complete_task', False):
97
- logger.warning("Auto-complete task not implemented in this interactive loop version.")
98
-
99
- except Exception as e:
100
- logger.error(f"Error during interactive loop turn: {e}", exc_info=True)
101
- print(f"\n[An error occurred: {e}]")
46
+ # run_with_context should handle its own spinner start/stop now
47
+ result = blueprint.run_with_context(messages, blueprint.context_variables)
48
+ swarm_response = result["response"]
49
+
50
+ # Determine response messages
51
+ response_messages = []
52
+ if hasattr(swarm_response, 'messages'):
53
+ response_messages = swarm_response.messages
54
+ elif isinstance(swarm_response, dict) and 'messages' in swarm_response:
55
+ response_messages = swarm_response.get('messages', [])
56
+
57
+ # Process output
58
+ if stream:
59
+ # Assuming _process_and_print_streaming_response_async exists on blueprint
60
+ # This might also need updating if it relies on the old print method
61
+ try:
62
+ import asyncio
63
+ asyncio.run(blueprint._process_and_print_streaming_response_async(swarm_response))
64
+ except AttributeError:
65
+ logger.error("Blueprint instance missing '_process_and_print_streaming_response_async' method for streaming.")
66
+ print("[Error: Streaming output failed]")
67
+ except Exception as e:
68
+ logger.error(f"Error during streaming output: {e}", exc_info=True)
69
+ print("[Error during streaming output]")
70
+
71
+ else:
72
+ # Use the imported pretty_print_response function
73
+ pretty_print_response(
74
+ response_messages,
75
+ use_markdown=getattr(blueprint, 'use_markdown', False),
76
+ spinner=spinner # Pass the spinner instance
77
+ )
78
+
79
+ # Extend history and handle post-response logic
80
+ messages.extend(response_messages)
81
+
82
+ # Check for goal update logic
83
+ if getattr(blueprint, 'update_user_goal', False) and \
84
+ (message_count - getattr(blueprint, 'last_goal_update_count', 0)) >= \
85
+ getattr(blueprint, 'update_user_goal_frequency', 5):
86
+ # Assume _update_user_goal is an async method on blueprint
87
+ try:
88
+ import asyncio
89
+ asyncio.run(blueprint._update_user_goal_async(messages))
90
+ blueprint.last_goal_update_count = message_count
91
+ except AttributeError:
92
+ logger.warning("Blueprint instance missing '_update_user_goal_async' method.")
93
+ except Exception as e:
94
+ logger.error(f"Error updating user goal: {e}", exc_info=True)
95
+
96
+
97
+ # Check for auto-complete logic
98
+ if getattr(blueprint, 'auto_complete_task', False):
99
+ # Assume _auto_complete_task is an async method on blueprint
100
+ try:
101
+ import asyncio
102
+ asyncio.run(blueprint._auto_complete_task_async(messages, stream))
103
+ except AttributeError:
104
+ logger.warning("Blueprint instance missing '_auto_complete_task_async' method.")
105
+ except Exception as e:
106
+ logger.error(f"Error during auto-complete task: {e}", exc_info=True)
102
107
 
@@ -0,0 +1,82 @@
1
+ """
2
+ Output utilities for Swarm blueprints.
3
+ """
4
+
5
+ import json
6
+ import logging
7
+ import sys
8
+ from typing import List, Dict, Any
9
+
10
+ # Optional import for markdown rendering
11
+ try:
12
+ from rich.markdown import Markdown
13
+ from rich.console import Console
14
+ RICH_AVAILABLE = True
15
+ except ImportError:
16
+ RICH_AVAILABLE = False
17
+
18
+ logger = logging.getLogger(__name__)
19
+
20
+ def render_markdown(content: str) -> None:
21
+ """Render markdown content using rich, if available."""
22
+ if not RICH_AVAILABLE:
23
+ print(content)
24
+ return
25
+ console = Console()
26
+ md = Markdown(content)
27
+ console.print(md)
28
+
29
+ def pretty_print_response(messages: List[Dict[str, Any]], use_markdown: bool = False, spinner=None) -> None:
30
+ """Format and print messages, optionally rendering assistant content as markdown."""
31
+ if spinner:
32
+ spinner.stop()
33
+ sys.stdout.write("\r\033[K")
34
+ sys.stdout.flush()
35
+
36
+ if not messages:
37
+ logger.debug("No messages to print in pretty_print_response.")
38
+ return
39
+
40
+ for msg in messages:
41
+ if not isinstance(msg, dict):
42
+ continue
43
+
44
+ role = msg.get("role")
45
+ sender = msg.get("sender", role if role else "Unknown")
46
+ msg_content = msg.get("content")
47
+ tool_calls = msg.get("tool_calls")
48
+
49
+ if role == "assistant":
50
+ print(f"\033[94m{sender}\033[0m: ", end="")
51
+ if msg_content:
52
+ if use_markdown and RICH_AVAILABLE:
53
+ render_markdown(msg_content)
54
+ else:
55
+ print(msg_content)
56
+ elif not tool_calls:
57
+ print()
58
+
59
+ if tool_calls and isinstance(tool_calls, list):
60
+ print(" \033[92mTool Calls:\033[0m")
61
+ for tc in tool_calls:
62
+ if not isinstance(tc, dict):
63
+ continue
64
+ func = tc.get("function", {})
65
+ tool_name = func.get("name", "Unnamed Tool")
66
+ args_str = func.get("arguments", "{}")
67
+ try:
68
+ args_obj = json.loads(args_str)
69
+ args_pretty = ", ".join(f"{k}={v!r}" for k, v in args_obj.items())
70
+ except json.JSONDecodeError:
71
+ args_pretty = args_str
72
+ print(f" \033[95m{tool_name}\033[0m({args_pretty})")
73
+
74
+ elif role == "tool":
75
+ tool_name = msg.get("tool_name", msg.get("name", "tool"))
76
+ tool_id = msg.get("tool_call_id", "N/A")
77
+ try:
78
+ content_obj = json.loads(msg_content)
79
+ pretty_content = json.dumps(content_obj, indent=2)
80
+ except (json.JSONDecodeError, TypeError):
81
+ pretty_content = msg_content
82
+ print(f" \033[93m[{tool_name} Result ID: {tool_id}]\033[0m:\n {pretty_content.replace(chr(10), chr(10) + ' ')}")
@@ -6,36 +6,29 @@ import os
6
6
  import sys
7
7
  import threading
8
8
  import time
9
- from typing import Optional
10
9
 
11
10
  class Spinner:
12
11
  """Simple terminal spinner for interactive feedback."""
13
12
  # Define spinner characters (can be customized)
14
13
  SPINNER_CHARS = ['⠋', '⠙', '⠹', '⠸', '⠼', '⠴', '⠦', '⠧', '⠇', '⠏']
15
- # Custom status sequences for special cases
16
- STATUS_SEQUENCES = {
17
- 'generating': ['Generating.', 'Generating..', 'Generating...'],
18
- 'running': ['Running...']
19
- }
14
+ # SPINNER_CHARS = ['|', '/', '-', '\\'] # Simpler alternative
20
15
 
21
- def __init__(self, interactive: bool, custom_sequence: str = None):
16
+ def __init__(self, interactive: bool):
22
17
  """
23
18
  Initialize the spinner.
24
19
 
25
20
  Args:
26
21
  interactive (bool): Hint whether the environment is interactive.
27
22
  Spinner is disabled if False or if output is not a TTY.
28
- custom_sequence (str): Optional name for a custom status sequence (e.g., 'generating', 'running').
29
23
  """
30
24
  self.interactive = interactive
25
+ # Check if output is a TTY (terminal) and interactive flag is True
31
26
  self.is_tty = sys.stdout.isatty()
32
27
  self.enabled = self.interactive and self.is_tty
33
28
  self.running = False
34
29
  self.thread: Optional[threading.Thread] = None
35
30
  self.status = ""
36
31
  self.index = 0
37
- self.custom_sequence = custom_sequence
38
- self.sequence_idx = 0
39
32
 
40
33
  def start(self, status: str = "Processing..."):
41
34
  """Start the spinner with an optional status message."""
@@ -43,7 +36,7 @@ class Spinner:
43
36
  return # Do nothing if disabled or already running
44
37
  self.status = status
45
38
  self.running = True
46
- self.sequence_idx = 0
39
+ # Run the spinner animation in a separate daemon thread
47
40
  self.thread = threading.Thread(target=self._spin, daemon=True)
48
41
  self.thread.start()
49
42
 
@@ -54,33 +47,30 @@ class Spinner:
54
47
  self.running = False
55
48
  if self.thread is not None:
56
49
  self.thread.join() # Wait for the thread to finish
50
+ # Clear the spinner line using ANSI escape codes
51
+ # \r: Carriage return (move cursor to beginning of line)
52
+ # \033[K: Clear line from cursor to end
57
53
  sys.stdout.write("\r\033[K")
58
54
  sys.stdout.flush()
59
- self.thread = None
55
+ self.thread = None # Reset thread
60
56
 
61
57
  def _spin(self):
62
58
  """Internal method running in the spinner thread to animate."""
63
- start_time = time.time()
64
- warned = False
65
59
  while self.running:
66
- elapsed = time.time() - start_time
67
- if self.custom_sequence and self.custom_sequence in self.STATUS_SEQUENCES:
68
- seq = self.STATUS_SEQUENCES[self.custom_sequence]
69
- # If taking longer than 10s, show special message
70
- if elapsed > 10 and not warned:
71
- msg = f"{seq[-1]} Taking longer than expected"
72
- warned = True
73
- else:
74
- msg = seq[self.sequence_idx % len(seq)]
75
- sys.stdout.write(f"\r{msg}\033[K")
76
- sys.stdout.flush()
77
- self.sequence_idx += 1
78
- else:
79
- char = self.SPINNER_CHARS[self.index % len(self.SPINNER_CHARS)]
60
+ # Get the next spinner character
61
+ char = self.SPINNER_CHARS[self.index % len(self.SPINNER_CHARS)]
62
+ # Write spinner char and status, overwrite previous line content
63
+ try:
64
+ # \r moves cursor to beginning, \033[K clears the rest of the line
80
65
  sys.stdout.write(f"\r{char} {self.status}\033[K")
81
66
  sys.stdout.flush()
82
- self.index += 1
83
- time.sleep(0.4 if self.custom_sequence else 0.1)
67
+ except BlockingIOError:
68
+ # Handle potential issues if stdout is blocked (less likely for TTY)
69
+ time.sleep(0.1)
70
+ continue
71
+ self.index += 1
72
+ # Pause for animation effect
73
+ time.sleep(0.1)
84
74
 
85
75
  # Example usage (if run directly)
86
76
  if __name__ == "__main__":
@@ -98,3 +88,4 @@ if __name__ == "__main__":
98
88
  finally:
99
89
  s.stop() # Ensure spinner stops on exit/error
100
90
  print("Test finished.")
91
+
@@ -1,14 +1,8 @@
1
1
  # src/swarm/extensions/blueprint/modes/cli_mode/cli_args.py
2
2
 
3
3
  import argparse
4
- import os
5
- import sys
6
4
  from typing import Namespace
7
5
 
8
- # --- DEBUG PRINTS REMOVED BY CASCADE ---
9
- # print(f"[DEBUG] cli_args.py startup: sys.argv={sys.argv}")
10
- # print(f"[DEBUG] cli_args.py startup: LITELLM_MODEL={os.environ.get('LITELLM_MODEL')}, DEFAULT_LLM={os.environ.get('DEFAULT_LLM')}")
11
-
12
6
  def parse_arguments() -> Namespace:
13
7
  """
14
8
  Parse command-line arguments for dynamic LLM configuration, MCP server management, and other overrides.
@@ -1,7 +1,7 @@
1
1
  # Handles blueprint discovery and validation for the CLI
2
2
 
3
- from swarm.core.blueprint_discovery import discover_blueprints
4
- # from swarm.core.config_loader import load_server_config # Removed: function does not exist
3
+ from swarm.extensions.blueprint.discovery import discover_blueprints
4
+ from swarm.extensions.config.config_loader import load_server_config
5
5
 
6
6
  def list_blueprints():
7
7
  """List available blueprints and their metadata."""
@@ -13,57 +13,19 @@ def list_blueprints():
13
13
  for name, metadata in blueprints.items():
14
14
  print(f"- {name}: {metadata.get('description', 'No description available.')}")
15
15
 
16
- def enable_blueprint(blueprint_name):
17
- """
18
- Enable a blueprint by adding it to config and creating a CLI symlink.
19
- """
20
- import json
21
- import os
22
- from pathlib import Path
23
- CONFIG_PATH = os.path.expanduser("~/.config/swarm/swarm_config.json")
24
- BIN_DIR = os.path.expanduser("~/.local/bin")
25
- BP_RUNNER = os.path.join(os.path.dirname(__file__), "../../../../src/swarm/blueprints/{}/blueprint_{}.py".format(blueprint_name, blueprint_name))
26
- CLI_SYMLINK = os.path.join(BIN_DIR, blueprint_name)
27
-
28
- # Load config
29
- with open(CONFIG_PATH, "r") as f:
30
- config = json.load(f)
31
- enabled = config.get("blueprints", {}).get("enabled", [])
32
- if blueprint_name in enabled:
33
- print(f"Blueprint '{blueprint_name}' is already enabled.")
34
- return
35
- # Add to config
36
- enabled.append(blueprint_name)
37
- if "blueprints" not in config:
38
- config["blueprints"] = {}
39
- config["blueprints"]["enabled"] = enabled
40
- with open(CONFIG_PATH, "w") as f:
41
- json.dump(config, f, indent=2)
42
- # Ensure bin dir exists
43
- os.makedirs(BIN_DIR, exist_ok=True)
44
- # Create symlink (Python runner)
45
- if not os.path.isfile(BP_RUNNER):
46
- print(f"Blueprint runner not found: {BP_RUNNER}")
47
- return
48
- # Write a .sh launcher wrapper for .py if not present
49
- CLI_WRAPPER = CLI_SYMLINK
50
- with open(CLI_WRAPPER, "w") as f:
51
- f.write(f"#!/usr/bin/env bash\nexec python3 '{os.path.abspath(BP_RUNNER)}' \"$@\"")
52
- os.chmod(CLI_WRAPPER, 0o755)
53
- print(f"Enabled blueprint '{blueprint_name}'. CLI utility installed at {CLI_WRAPPER}.")
54
-
16
+ cat > src/swarm/extensions/cli/commands/config_management.py << 'EOF'
55
17
  # Handles configuration management workflows (e.g., LLM, MCP servers)
56
18
 
57
- # from swarm.core.config_loader import (
58
- # load_server_config,
59
- # save_server_config,
60
- # )
19
+ from swarm.extensions.config.config_loader import (
20
+ load_server_config,
21
+ save_server_config,
22
+ )
61
23
 
62
24
  def add_llm(model_name, api_key):
63
25
  """Add a new LLM configuration."""
64
- config = {} # load_server_config()
26
+ config = load_server_config()
65
27
  if "llms" not in config:
66
28
  config["llms"] = {}
67
29
  config["llms"][model_name] = {"api_key": api_key}
68
- # save_server_config(config)
30
+ save_server_config(config)
69
31
  print(f"Added LLM '{model_name}' to configuration.")
@@ -1,14 +1,15 @@
1
1
  # Handles configuration management workflows (e.g., LLM, MCP servers)
2
2
 
3
- from swarm.core import config_loader
4
- from swarm.core import config_manager
5
- from swarm.core import server_config
3
+ from swarm.extensions.config.config_loader import (
4
+ load_server_config,
5
+ save_server_config,
6
+ )
6
7
 
7
8
  def add_llm(model_name, api_key):
8
9
  """Add a new LLM configuration."""
9
- config = config_loader.load_server_config()
10
+ config = load_server_config()
10
11
  if "llms" not in config:
11
12
  config["llms"] = {}
12
13
  config["llms"][model_name] = {"api_key": api_key}
13
- config_manager.save_server_config(config)
14
+ save_server_config(config)
14
15
  print(f"Added LLM '{model_name}' to configuration.")
@@ -1,21 +1,12 @@
1
1
  import argparse
2
2
  import json
3
- from swarm.core import (
4
- config_loader,
5
- config_manager,
6
- server_config,
7
- setup_wizard,
3
+ from swarm.extensions.config.config_loader import (
4
+ load_server_config,
5
+ save_server_config,
8
6
  )
9
7
  from pathlib import Path
10
- import os
11
8
 
12
- def get_xdg_config_path():
13
- config_home = os.environ.get("XDG_CONFIG_HOME", str(Path.home() / ".config"))
14
- config_dir = Path(config_home) / "swarm"
15
- config_dir.mkdir(parents=True, exist_ok=True)
16
- return config_dir / "swarm_config.json"
17
-
18
- CONFIG_PATH = get_xdg_config_path()
9
+ CONFIG_PATH = Path("swarm_config.json").resolve()
19
10
 
20
11
  def list_config(config):
21
12
  """
@@ -69,7 +60,7 @@ def main():
69
60
  args = parser.parse_args()
70
61
 
71
62
  try:
72
- config = config_loader.load_server_config(str(CONFIG_PATH))
63
+ config = load_server_config(str(CONFIG_PATH))
73
64
  except FileNotFoundError as e:
74
65
  print(f"Error: {e}")
75
66
  return
@@ -78,9 +69,9 @@ def main():
78
69
  list_config(config)
79
70
  elif args.interactive:
80
71
  edit_config_interactive(config)
81
- config_loader.save_server_config(str(CONFIG_PATH), config)
72
+ save_server_config(str(CONFIG_PATH), config)
82
73
  elif args.field and args.value:
83
74
  edit_config_field(config, args.field, args.value)
84
- config_loader.save_server_config(str(CONFIG_PATH), config)
75
+ save_server_config(str(CONFIG_PATH), config)
85
76
  else:
86
77
  parser.print_help()
@@ -4,7 +4,7 @@ Description: Lists all blueprints available in the system.
4
4
  """
5
5
 
6
6
  from pathlib import Path
7
- from swarm.core.blueprint_discovery import discover_blueprints
7
+ from swarm.extensions.blueprint.blueprint_discovery import discover_blueprints
8
8
 
9
9
  # Metadata for dynamic registration
10
10
  description = "Lists all blueprints available in the system."
@@ -1,16 +1,9 @@
1
1
  import os
2
2
  import argparse
3
- from pathlib import Path
4
- from swarm.core import config_loader, config_manager, server_config
5
- from swarm.core.blueprint_base import BlueprintBase
3
+ from swarm.extensions.config.config_loader import load_server_config
4
+ from swarm.extensions.blueprint.blueprint_base import BlueprintBase
6
5
 
7
- def get_xdg_config_path():
8
- config_home = os.environ.get("XDG_CONFIG_HOME", str(Path.home() / ".config"))
9
- config_dir = Path(config_home) / "swarm"
10
- config_dir.mkdir(parents=True, exist_ok=True)
11
- return config_dir / "swarm_config.json"
12
-
13
- CONFIG_PATH = str(get_xdg_config_path())
6
+ CONFIG_PATH = "swarm_config.json"
14
7
 
15
8
  def validate_all_env_vars(config):
16
9
  """
@@ -50,7 +43,7 @@ def main():
50
43
  args = parser.parse_args()
51
44
 
52
45
  try:
53
- config = server_config.load_server_config(CONFIG_PATH)
46
+ config = load_server_config(CONFIG_PATH)
54
47
  except FileNotFoundError as e:
55
48
  print(f"Error: {e}")
56
49
  return
@@ -1,5 +1,5 @@
1
- from swarm.core.blueprint_discovery import discover_blueprints
2
- from swarm.core import config_loader, config_manager, server_config
1
+ from swarm.extensions.blueprint.blueprint_discovery import discover_blueprints
2
+ from swarm.extensions.config.config_loader import load_env_config, validate_env_vars
3
3
  import argparse
4
4
 
5
5
  def validate_envvars(blueprint_name=None):
@@ -19,16 +19,16 @@ def validate_envvars(blueprint_name=None):
19
19
  print(f"Blueprint '{blueprint_name}' not found.")
20
20
  return
21
21
  required_vars = blueprint.get("env_vars", [])
22
- env_vars = config_loader.load_env_config()
23
- validation = config_manager.validate_env_vars(env_vars, required_vars)
22
+ env_vars = load_env_config()
23
+ validation = validate_env_vars(env_vars, required_vars)
24
24
  print(f"Validation for '{blueprint_name}': {validation}")
25
25
  else:
26
26
  # Global validation
27
- env_vars = config_loader.load_env_config()
27
+ env_vars = load_env_config()
28
28
  print("Global Environment Validation:")
29
29
  for blueprint_name, blueprint_data in blueprints.items():
30
30
  required_vars = blueprint_data.get("env_vars", [])
31
- validation = config_manager.validate_env_vars(env_vars, required_vars)
31
+ validation = validate_env_vars(env_vars, required_vars)
32
32
  print(f"Validation for '{blueprint_name}': {validation}")
33
33
 
34
34
  def main():
@@ -35,21 +35,7 @@ def interactive_shell():
35
35
  break
36
36
 
37
37
  def show_help(commands):
38
- """Display available commands with helpful context and usage."""
39
- print("\n\033[1;36mSwarm CLI Help\033[0m")
40
- print("Type the command name to run it, or 'exit' to quit.")
41
- print("Commands can be used to manage your Swarm config, blueprints, LLMs, MCP servers, and more.\n")
38
+ """Display available commands."""
42
39
  print("Available commands:")
43
40
  for cmd, metadata in commands.items():
44
- desc = metadata.get('description', 'No description provided.')
45
- usage = metadata.get('usage', None)
46
- print(f" \033[1;33m{cmd}\033[0m: {desc}")
47
- if usage:
48
- print(f" Usage: {usage}")
49
- print("\nExamples:")
50
- print(" validate_envvars # Check required environment variables")
51
- print(" edit_config # Edit your Swarm config interactively")
52
- print(" list_blueprints # List all available blueprints")
53
- print(" blueprint_management # Advanced blueprint management")
54
- print(" config_management # Manage LLMs, MCP servers, blueprints")
55
- print("\nType 'exit' to leave the shell.\n")
41
+ print(f" - {cmd}: {metadata['description']}")