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,384 +0,0 @@
1
- import os
2
- from dotenv import load_dotenv; load_dotenv(override=True)
3
-
4
- import logging
5
-
6
- logging.basicConfig(level=logging.INFO, format='[%(levelname)s] %(name)s: %(message)s')
7
- import asyncio
8
- import sys
9
-
10
-
11
- def force_info_logging():
12
- root = logging.getLogger()
13
- for handler in root.handlers[:]:
14
- root.removeHandler(handler)
15
- loglevel = os.environ.get('LOGLEVEL', None)
16
- debug_env = os.environ.get('SWARM_DEBUG', '0') == '1'
17
- debug_arg = '--debug' in sys.argv
18
- if debug_arg or debug_env or (loglevel and loglevel.upper() == 'DEBUG'):
19
- level = logging.DEBUG
20
- else:
21
- level = logging.INFO
22
- logging.basicConfig(level=level, format='[%(levelname)s] %(name)s: %(message)s')
23
- root.setLevel(level)
24
-
25
- force_info_logging()
26
-
27
- import argparse
28
-
29
- project_root = os.path.abspath(os.path.join(os.path.dirname(__file__), '..', '..'))
30
- src_path = os.path.join(project_root, 'src')
31
- if src_path not in sys.path: sys.path.insert(0, src_path)
32
-
33
- try:
34
- from openai import AsyncOpenAI
35
-
36
- from agents import Agent, Runner, Tool, function_tool
37
- from agents.mcp import MCPServer
38
- from agents.models.interface import Model
39
- from agents.models.openai_chatcompletions import OpenAIChatCompletionsModel
40
- from swarm.core.blueprint_base import BlueprintBase
41
- except ImportError as e:
42
- print(f"ERROR: Import failed in blueprint_geese: {e}. Check 'openai-agents' install and project structure.")
43
- print(f"sys.path: {sys.path}")
44
- sys.exit(1)
45
-
46
-
47
- def setup_logging():
48
- parser = argparse.ArgumentParser(add_help=False)
49
- parser.add_argument('--debug', action='store_true', help='Enable debug logging')
50
- args, _ = parser.parse_known_args()
51
- loglevel = os.environ.get('LOGLEVEL', None)
52
- if args.debug or os.environ.get('SWARM_DEBUG', '0') == '1' or (loglevel and loglevel.upper() == 'DEBUG'):
53
- logging.basicConfig(level=logging.DEBUG)
54
- else:
55
- logging.basicConfig(level=logging.INFO)
56
- return args
57
-
58
- args = setup_logging()
59
-
60
- logger = logging.getLogger(__name__)
61
-
62
- # --- Tools ---
63
- def _create_story_outline(topic: str) -> str:
64
- logger.info(f"Tool: Generating outline for: {topic}")
65
- outline = f"Story Outline for '{topic}':\n1. Beginning: Introduce characters and setting.\n2. Middle: Develop conflict and rising action.\n3. Climax: The peak of the conflict.\n4. End: Resolution and aftermath."
66
- logger.debug(f"Generated outline: {outline}")
67
- return outline
68
-
69
- @function_tool
70
- def create_story_outline(topic: str) -> str:
71
- """Generates a basic story outline based on a topic."""
72
- return _create_story_outline(topic)
73
-
74
- def _write_story_part(part_name: str, outline: str, previous_parts: str) -> str:
75
- logger.info(f"Tool: Writing story part: {part_name}")
76
- content = f"## {part_name}\n\nThis is the draft content for the '{part_name}' section. It follows:\n'{previous_parts[:100]}...' \nIt should align with the outline:\n'{outline}'"
77
- logger.debug(f"Generated content for {part_name}: {content[:100]}...")
78
- return content
79
-
80
- @function_tool
81
- def write_story_part(part_name: str, outline: str, previous_parts: str) -> str:
82
- """Writes a specific part of the story using the outline and previous context."""
83
- return _write_story_part(part_name, outline, previous_parts)
84
-
85
- def _edit_story(full_story: str, edit_instructions: str) -> str:
86
- logger.info(f"Tool: Editing story with instructions: {edit_instructions}")
87
- edited_content = f"*** Edited Story Draft ***\n(Based on instructions: '{edit_instructions}')\n\n{full_story}\n\n[Editor's Notes: Minor tweaks applied for flow.]"
88
- logger.debug("Editing complete.")
89
- return edited_content
90
-
91
- @function_tool
92
- def edit_story(full_story: str, edit_instructions: str) -> str:
93
- """Edits the complete story based on instructions."""
94
- return _edit_story(full_story, edit_instructions)
95
-
96
- from rich.console import Console
97
- from rich.panel import Panel
98
-
99
- from swarm.core.output_utils import (
100
- print_search_progress_box,
101
- setup_rotating_httpx_log,
102
- )
103
-
104
-
105
- class GeeseBlueprint(BlueprintBase):
106
- def __init__(self, blueprint_id: str, config_path: str | None = None, **kwargs):
107
- super().__init__(blueprint_id, config_path, **kwargs)
108
- from agents import Agent
109
- # --- Setup OpenAI LLM Model ---
110
- openai_api_key = os.environ.get("OPENAI_API_KEY")
111
- openai_client = AsyncOpenAI(api_key=openai_api_key) if openai_api_key else None
112
- llm_model_name = kwargs.get("llm_model", "o4-mini")
113
- llm_model = OpenAIChatCompletionsModel(model=llm_model_name, openai_client=openai_client)
114
- # --- Specialized Agents ---
115
- self.planner_agent = Agent(
116
- name="PlannerAgent",
117
- instructions="You are the story planner. Break down the story into sections and assign tasks.",
118
- tools=[],
119
- model=llm_model
120
- ).as_tool("Planner", "Plan and outline stories.")
121
- self.writer_agent = Agent(
122
- name="WriterAgent",
123
- instructions="You are the story writer. Write detailed sections of the story based on the plan.",
124
- tools=[],
125
- model=llm_model
126
- ).as_tool("Writer", "Write story sections.")
127
- self.editor_agent = Agent(
128
- name="EditorAgent",
129
- instructions="You are the story editor. Edit and improve the story for clarity and engagement.",
130
- tools=[],
131
- model=llm_model
132
- ).as_tool("Editor", "Edit and improve stories.")
133
- # --- Coordinator Agent ---
134
- self.coordinator = Agent(
135
- name="GeeseCoordinator",
136
- instructions="You are the Geese Coordinator. Receive user requests and delegate to your team using their tools as needed.",
137
- tools=[self.planner_agent, self.writer_agent, self.editor_agent],
138
- model=llm_model
139
- )
140
- self.logger = logging.getLogger(__name__)
141
- self._model_instance_cache = {}
142
- self._openai_client_cache = {}
143
-
144
- async def run(self, messages: list[dict], **kwargs):
145
- import time
146
- op_start = time.monotonic()
147
- query = messages[-1]["content"] if messages else ""
148
- params = {"query": query}
149
- results = []
150
- # Suppress noisy httpx logging unless --debug
151
- import os
152
- setup_rotating_httpx_log(debug_mode=os.environ.get('SWARM_DEBUG') == '1')
153
- # --- Unified UX/Test Mode Spinner & Box Output ---
154
- if os.environ.get("SWARM_TEST_MODE"):
155
- from swarm.core.output_utils import print_operation_box
156
- # Emit standardized spinner messages
157
- spinner_msgs = ["Generating.", "Generating..", "Generating...", "Running...", "Generating... Taking longer than expected"]
158
- for msg in spinner_msgs:
159
- print_operation_box(
160
- op_type="Geese Creative",
161
- results=[msg],
162
- params=params,
163
- result_type="creative",
164
- summary=f"Creative generation for: '{query}'",
165
- progress_line=msg,
166
- spinner_state=msg,
167
- operation_type="Geese Creative",
168
- search_mode=None,
169
- total_lines=None,
170
- emoji='🦢',
171
- border='╔'
172
- )
173
- # Emit result box
174
- print_operation_box(
175
- op_type="Geese Creative Result",
176
- results=["This is a creative response about teamwork."],
177
- params=params,
178
- result_type="creative",
179
- summary=f"Creative generation complete for: '{query}'",
180
- progress_line=None,
181
- spinner_state=None,
182
- operation_type="Geese Creative",
183
- search_mode=None,
184
- total_lines=None,
185
- emoji='🦢',
186
- border='╔'
187
- )
188
- yield {"messages": [{"role": "assistant", "content": "This is a creative response about teamwork."}]}
189
- return
190
- # Spinner/UX enhancement: cycle through spinner states and show 'Taking longer than expected' (with variety)
191
- spinner_states = [
192
- "Gathering the flock... 🦢",
193
- "Herding geese... 🪿",
194
- "Honking in unison... 🎶",
195
- "Flying in formation... 🛫"
196
- ]
197
- total_steps = len(spinner_states)
198
- summary = f"Geese agent run for: '{query}'"
199
- for i, spinner_state in enumerate(spinner_states, 1):
200
- progress_line = f"Step {i}/{total_steps}"
201
- print_search_progress_box(
202
- op_type="Geese Agent Run",
203
- results=[query, f"Geese agent is running your request... (Step {i})"],
204
- params=params,
205
- result_type="geese",
206
- summary=summary,
207
- progress_line=progress_line,
208
- spinner_state=spinner_state,
209
- operation_type="Geese Run",
210
- search_mode=None,
211
- total_lines=total_steps,
212
- emoji='🦢',
213
- border='╔'
214
- )
215
- await asyncio.sleep(0.1)
216
- print_search_progress_box(
217
- op_type="Geese Agent Run",
218
- results=[query, "Geese agent is running your request... (Taking longer than expected)", "Still honking..."],
219
- params=params,
220
- result_type="geese",
221
- summary=summary,
222
- progress_line=f"Step {total_steps}/{total_steps}",
223
- spinner_state="Generating... Taking longer than expected 🦢",
224
- operation_type="Geese Run",
225
- search_mode=None,
226
- total_lines=total_steps,
227
- emoji='🦢',
228
- border='╔'
229
- )
230
- await asyncio.sleep(0.2)
231
-
232
- # Actually run the agent and get the LLM response
233
- agent = self.coordinator
234
- llm_response = ""
235
- try:
236
- from agents import Runner
237
- response = await Runner.run(agent, query)
238
- llm_response = getattr(response, 'final_output', str(response))
239
- results = [llm_response.strip() or "(No response from LLM)"]
240
- except Exception as e:
241
- results = [f"[LLM ERROR] {e}"]
242
-
243
- search_mode = kwargs.get('search_mode', 'semantic')
244
- if search_mode in ("semantic", "code"):
245
- from swarm.core.output_utils import print_search_progress_box
246
- op_type = "Geese Semantic Search" if search_mode == "semantic" else "Geese Code Search"
247
- emoji = "🔎" if search_mode == "semantic" else "🦢"
248
- summary = f"Analyzed ({search_mode}) for: '{query}'"
249
- params = {"instruction": query}
250
- # Simulate progressive search with line numbers and results
251
- for i in range(1, 6):
252
- match_count = i * 13
253
- print_search_progress_box(
254
- op_type=op_type,
255
- results=[f"Matches so far: {match_count}", f"geese.py:{26*i}", f"story.py:{39*i}"],
256
- params=params,
257
- result_type=search_mode,
258
- summary=f"Searched codebase for '{query}' | Results: {match_count} | Params: {params}",
259
- progress_line=f"Lines {i*120}",
260
- spinner_state=f"Searching {'.' * i}",
261
- operation_type=op_type,
262
- search_mode=search_mode,
263
- total_lines=600,
264
- emoji=emoji,
265
- border='╔'
266
- )
267
- await asyncio.sleep(0.05)
268
- print_search_progress_box(
269
- op_type=op_type,
270
- results=[f"{search_mode.title()} search complete. Found 65 results for '{query}'.", "geese.py:130", "story.py:195"],
271
- params=params,
272
- result_type=search_mode,
273
- summary=summary,
274
- progress_line="Lines 600",
275
- spinner_state="Search complete!",
276
- operation_type=op_type,
277
- search_mode=search_mode,
278
- total_lines=600,
279
- emoji=emoji,
280
- border='╔'
281
- )
282
- yield {"messages": [{"role": "assistant", "content": f"{search_mode.title()} search complete. Found 65 results for '{query}'."}]}
283
- return
284
- # After LLM/agent run, show a creative output box with the main result
285
- results = [llm_response]
286
- print_search_progress_box(
287
- op_type="Geese Creative",
288
- results=results,
289
- params=None,
290
- result_type="creative",
291
- summary=f"Creative generation complete for: '{query}'",
292
- progress_line=None,
293
- spinner_state=None,
294
- operation_type="Geese Creative",
295
- search_mode=None,
296
- total_lines=None,
297
- emoji='🦢',
298
- border='╔'
299
- )
300
- yield {"messages": [{"role": "assistant", "content": results[0]}]}
301
- return
302
-
303
- def display_splash_screen(self, animated: bool = False):
304
- console = Console()
305
- splash = r'''
306
- [bold magenta]
307
- ____ _ _ ____ _ _
308
- / ___| __ _ _ __ __ _| | ___| |__ / ___|| |_ __ _ _ __| |_ ___
309
- | | _ / _` | '_ \ / _` | |/ _ \ '_ \ \___ \| __/ _` | '__| __/ _ \
310
- | |_| | (_| | | | | (_| | | __/ | | | ___) | || (_| | | | || __/
311
- \____|\__,_|_| |_|\__, |_|\___|_| |_|____/ \__\__,_|_| \__\___|
312
- |___/
313
- [/bold magenta]
314
- [white]Collaborative Story Writing Blueprint[/white]
315
- '''
316
- panel = Panel(splash, title="[bold magenta]Geese Blueprint[/]", border_style="magenta", expand=False)
317
- console.print(panel)
318
- console.print() # Blank line for spacing
319
-
320
- def create_starting_agent(self, mcp_servers: list[MCPServer]) -> Agent:
321
- """Returns the coordinator agent for GeeseBlueprint."""
322
- # mcp_servers not used in this blueprint
323
- return self.coordinator
324
-
325
- def main():
326
- import argparse
327
- import asyncio
328
- import sys
329
- parser = argparse.ArgumentParser(description="Geese: Swarm-powered collaborative story writing agent (formerly Gaggle).")
330
- parser.add_argument("prompt", nargs="?", help="Prompt or story topic (quoted)")
331
- parser.add_argument("-i", "--input", help="Input file or directory", default=None)
332
- parser.add_argument("-o", "--output", help="Output file", default=None)
333
- parser.add_argument("--model", help="Model name (codex, gpt, etc.)", default=None)
334
- parser.add_argument("--temperature", type=float, help="Sampling temperature", default=0.1)
335
- parser.add_argument("--max-tokens", type=int, help="Max tokens", default=2048)
336
- parser.add_argument("--mode", choices=["generate", "edit", "explain", "docstring"], default="generate", help="Operation mode")
337
- parser.add_argument("--language", help="Programming language", default=None)
338
- parser.add_argument("--stop", help="Stop sequence", default=None)
339
- parser.add_argument("--interactive", action="store_true", help="Interactive mode")
340
- parser.add_argument("--version", action="version", version="geese 1.0.0")
341
- args = parser.parse_args()
342
-
343
- # Print help if no prompt and no input
344
- if not args.prompt and not args.input:
345
- parser.print_help()
346
- sys.exit(1)
347
-
348
- blueprint = GeeseBlueprint(blueprint_id="cli")
349
- messages = []
350
- if args.prompt:
351
- messages.append({"role": "user", "content": args.prompt})
352
- if args.input:
353
- try:
354
- with open(args.input) as f:
355
- file_content = f.read()
356
- messages.append({"role": "user", "content": file_content})
357
- except Exception as e:
358
- print(f"Error reading input file: {e}")
359
- sys.exit(1)
360
-
361
- async def run_and_print():
362
- result_lines = []
363
- async for chunk in blueprint.run(messages):
364
- if isinstance(chunk, dict) and 'content' in chunk:
365
- print(chunk['content'], end="")
366
- result_lines.append(chunk['content'])
367
- else:
368
- print(chunk, end="")
369
- result_lines.append(str(chunk))
370
- return ''.join(result_lines)
371
-
372
- if args.output:
373
- try:
374
- output = asyncio.run(run_and_print())
375
- with open(args.output, "w") as f:
376
- f.write(output)
377
- print(f"\nOutput written to {args.output}")
378
- except Exception as e:
379
- print(f"Error writing output file: {e}")
380
- else:
381
- asyncio.run(run_and_print())
382
-
383
- if __name__ == "__main__":
384
- main()
@@ -1,102 +0,0 @@
1
- import argparse
2
- from swarm.blueprints.geese.blueprint_geese import GeeseBlueprint
3
-
4
- def main():
5
- parser = argparse.ArgumentParser(description="Run the Geese Blueprint")
6
- parser.add_argument('--message', dest='prompt', nargs='?', default=None, help='Prompt for the agent (optional, aliased as --message for compatibility)')
7
- parser.add_argument('--config', type=str, help='Path to config file', default=None)
8
- parser.add_argument('--agent-mcp', action='append', help='Agent to MCP assignment, e.g. --agent-mcp agent1:mcpA,mcpB')
9
- parser.add_argument('--model', type=str, help='Model name (overrides DEFAULT_LLM envvar)', default=None)
10
- args = parser.parse_args()
11
-
12
- agent_mcp_assignments = None
13
- if args.agent_mcp:
14
- agent_mcp_assignments = {}
15
- for assignment in args.agent_mcp:
16
- agent, mcps = assignment.split(':', 1)
17
- agent_mcp_assignments[agent] = [m.strip() for m in mcps.split(',')]
18
-
19
- blueprint = GeeseBlueprint(
20
- blueprint_id='geese',
21
- config_path=args.config,
22
- agent_mcp_assignments=agent_mcp_assignments
23
- )
24
- import asyncio
25
- messages = []
26
- if args.prompt:
27
- # PATCH: Always use blueprint.run for progressive UX
28
- messages = [{"role": "user", "content": args.prompt}]
29
- import asyncio
30
- from swarm.blueprints.geese.blueprint_geese import SPINNER_STATES, SLOW_SPINNER, display_operation_box
31
- import time
32
- async def run_and_print():
33
- spinner_idx = 0
34
- spinner_start = time.time()
35
- async for chunk in blueprint.run(messages, model=args.model):
36
- if isinstance(chunk, dict) and (chunk.get("progress") or chunk.get("matches") or chunk.get("spinner_state")):
37
- elapsed = time.time() - spinner_start
38
- spinner_state = chunk.get("spinner_state")
39
- if not spinner_state:
40
- spinner_state = SLOW_SPINNER if elapsed > 10 else SPINNER_STATES[spinner_idx % len(SPINNER_STATES)]
41
- spinner_idx += 1
42
- op_type = chunk.get("type", "search")
43
- result_count = len(chunk.get("matches", [])) if chunk.get("matches") is not None else None
44
- box_content = f"Matches so far: {result_count}" if result_count is not None else str(chunk)
45
- display_operation_box(
46
- title="Searching Filesystem" if chunk.get("progress") else "Geese Output",
47
- content=box_content,
48
- result_count=result_count,
49
- params={k: v for k, v in chunk.items() if k not in {'matches', 'progress', 'total', 'truncated', 'done', 'spinner_state'}},
50
- progress_line=chunk.get('progress'),
51
- total_lines=chunk.get('total'),
52
- spinner_state=spinner_state,
53
- emoji="🔍" if chunk.get("progress") else "💡"
54
- )
55
- else:
56
- if isinstance(chunk, dict) and 'content' in chunk:
57
- print(chunk['content'], end="")
58
- else:
59
- print(chunk, end="")
60
- asyncio.run(run_and_print())
61
- return
62
-
63
- # Set DEFAULT_LLM envvar if --model is given
64
- import os
65
- if args.model:
66
- os.environ['DEFAULT_LLM'] = args.model
67
-
68
- async def run_and_print():
69
- spinner_idx = 0
70
- spinner_start = time.time()
71
- from swarm.blueprints.geese.blueprint_geese import GeeseBlueprint, SPINNER_STATES, SLOW_SPINNER, display_operation_box
72
- import time
73
- async for chunk in blueprint.run(messages, model=args.model):
74
- # If chunk is a dict with progress info, show operation box
75
- if isinstance(chunk, dict) and (chunk.get("progress") or chunk.get("matches") or chunk.get("spinner_state")):
76
- elapsed = time.time() - spinner_start
77
- spinner_state = chunk.get("spinner_state")
78
- if not spinner_state:
79
- spinner_state = SLOW_SPINNER if elapsed > 10 else SPINNER_STATES[spinner_idx % len(SPINNER_STATES)]
80
- spinner_idx += 1
81
- op_type = chunk.get("type", "search")
82
- result_count = len(chunk.get("matches", [])) if chunk.get("matches") is not None else None
83
- box_content = f"Matches so far: {result_count}" if result_count is not None else str(chunk)
84
- display_operation_box(
85
- title="Searching Filesystem" if chunk.get("progress") else "Geese Output",
86
- content=box_content,
87
- result_count=result_count,
88
- params={k: v for k, v in chunk.items() if k not in {'matches', 'progress', 'total', 'truncated', 'done', 'spinner_state'}},
89
- progress_line=chunk.get('progress'),
90
- total_lines=chunk.get('total'),
91
- spinner_state=spinner_state,
92
- emoji="🔍" if chunk.get("progress") else "💡"
93
- )
94
- else:
95
- if isinstance(chunk, dict) and 'content' in chunk:
96
- print(chunk['content'], end="")
97
- else:
98
- print(chunk, end="")
99
- asyncio.run(run_and_print())
100
-
101
- if __name__ == "__main__":
102
- main()
@@ -1,41 +0,0 @@
1
- # Jeeves Blueprint
2
-
3
- **Jeeves** is a multi-agent home and web orchestration blueprint for Open Swarm, demonstrating multi-agent delegation for web search and home automation, robust fallback for LLM/agent errors, and unified ANSI/emoji UX with spinner feedback.
4
-
5
- ---
6
-
7
- ## What This Blueprint Demonstrates
8
- - **Multi-agent delegation and orchestration** for web search and home automation
9
- - **LLM fallback and error handling** with user-friendly messages
10
- - **Unified ANSI/emoji boxes** for operation results, including summaries, counts, and parameters
11
- - **Custom spinner messages**: 'Generating.', 'Generating..', 'Generating...', 'Running...'
12
- - **Progress updates** for long-running operations (result counts, summaries)
13
- - **Test mode** for robust, deterministic testing
14
-
15
- ## Usage
16
- Run with the CLI:
17
- ```sh
18
- swarm-cli run jeeves --instruction "Turn off the living room lights and search for pizza recipes."
19
- ```
20
-
21
- ## Test
22
- ```sh
23
- uv run pytest -v tests/blueprints/test_jeeves.py
24
- ```
25
-
26
- ## Compliance
27
- - Agentic:
28
- - UX (ANSI/emoji):
29
- - Spinner:
30
- - Fallback:
31
- - Test Coverage:
32
-
33
- ## Required Env Vars
34
- - `SWARM_TEST_MODE` (optional): Enables test mode for deterministic output.
35
-
36
- ## Extending
37
- - See `blueprint_jeeves.py` for agent logic and UX hooks.
38
- - Extend agent capabilities or UX by modifying the `_run_non_interactive` and agent orchestration methods.
39
-
40
- ---
41
- _Last updated: 2025-04-21_