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,349 +0,0 @@
1
- import logging
2
- import os
3
- import sys
4
- from typing import Dict, Any, List, ClassVar, Optional
5
- from swarm.blueprints.common.operation_box_utils import display_operation_box
6
-
7
- # Ensure src is in path for BlueprintBase import
8
- project_root = os.path.abspath(os.path.join(os.path.dirname(__file__), '..', '..'))
9
- src_path = os.path.join(project_root, 'src')
10
- if src_path not in sys.path: sys.path.insert(0, src_path)
11
-
12
- from typing import Optional
13
- from pathlib import Path
14
- try:
15
- from agents import Agent, Tool, function_tool, Runner
16
- from agents.mcp import MCPServer
17
- from agents.models.interface import Model
18
- from agents.models.openai_chatcompletions import OpenAIChatCompletionsModel
19
- from openai import AsyncOpenAI
20
- from swarm.core.blueprint_base import BlueprintBase
21
- except ImportError as e:
22
- print(f"ERROR: Import failed in StewieBlueprint: {e}. Check dependencies.")
23
- print(f"sys.path: {sys.path}")
24
- sys.exit(1)
25
-
26
- logger = logging.getLogger(__name__)
27
-
28
- # --- Agent Instructions ---
29
- # Keep instructions defined globally for clarity
30
-
31
- SHARED_INSTRUCTIONS = """
32
- You are part of the Grifton family WordPress team. Peter coordinates, Brian manages WordPress.
33
- Roles:
34
- - PeterGrifton (Coordinator): User interface, planning, delegates WP tasks via `BrianGrifton` Agent Tool.
35
- - BrianGrifton (WordPress Manager): Uses `server-wp-mcp` MCP tool (likely function `wp_call_endpoint`) to manage content based on Peter's requests.
36
- Respond ONLY to the agent who tasked you.
37
- """
38
-
39
- peter_instructions = (
40
- f"{SHARED_INSTRUCTIONS}\n\n"
41
- "YOUR ROLE: PeterGrifton, Coordinator. You handle user requests about WordPress.\n"
42
- "1. Understand the user's goal (create post, edit post, list sites, etc.).\n"
43
- "2. Delegate the task to Brian using the `BrianGrifton` agent tool.\n"
44
- "3. Provide ALL necessary details to Brian (content, title, site ID, endpoint details if known, method like GET/POST).\n"
45
- "4. Relay Brian's response (success, failure, IDs, data) back to the user clearly."
46
- )
47
-
48
- brian_instructions = (
49
- f"{SHARED_INSTRUCTIONS}\n\n"
50
- "YOUR ROLE: BrianGrifton, WordPress Manager. You interact with WordPress sites via the `server-wp-mcp` tool.\n"
51
- "1. Receive tasks from Peter.\n"
52
- "2. Determine the correct WordPress REST API endpoint and parameters required (e.g., `site`, `endpoint`, `method`, `params`).\n"
53
- "3. Call the MCP tool function (likely named `wp_call_endpoint` or similar provided by the MCP server) with the correct JSON arguments.\n"
54
- "4. Report the outcome (success confirmation, data returned, or error message) precisely back to Peter."
55
- )
56
-
57
- # --- Define the Blueprint ---
58
- class StewieBlueprint(BlueprintBase):
59
- def __init__(self, blueprint_id: str = "stewie", config=None, config_path=None, **kwargs):
60
- super().__init__(blueprint_id, config=config, config_path=config_path, **kwargs)
61
- self.blueprint_id = blueprint_id
62
- self.config_path = config_path
63
- self._config = config if config is not None else {}
64
- self._llm_profile_name = None
65
- self._llm_profile_data = None
66
- self._markdown_output = None
67
- # Add other attributes as needed for Stewie
68
- # ...
69
-
70
- def __init__(self, blueprint_id: str, config_path: Optional[Path] = None, **kwargs):
71
- import os
72
- # Try to force config_path to the correct file if not set
73
- if config_path is None:
74
- # Try CWD first (containerized runs may mount config here)
75
- cwd_path = os.path.abspath(os.path.join(os.getcwd(), 'swarm_config.json'))
76
- if os.path.exists(cwd_path):
77
- config_path = cwd_path
78
- else:
79
- # Fallback to project root relative to blueprint
80
- default_path = os.path.abspath(os.path.join(os.path.dirname(__file__), '../../../../swarm_config.json'))
81
- if os.path.exists(default_path):
82
- config_path = default_path
83
- else:
84
- # Final fallback: try /mnt/models/open-swarm-mcp/swarm_config.json (where the file is present)
85
- mnt_path = '/mnt/models/open-swarm-mcp/swarm_config.json'
86
- if os.path.exists(mnt_path):
87
- config_path = mnt_path
88
- super().__init__(blueprint_id, config_path=config_path, **kwargs)
89
- # Force config reload using BlueprintBase fallback logic
90
- # Patch: assign config to _config and always use self._config
91
- self._config = self._load_configuration()
92
- import pprint
93
- print(f"[STEWIE DEBUG] Loaded config from: {config_path}")
94
- pprint.pprint(self._config)
95
-
96
- """Manages WordPress content with a Stewie agent team using the `server-wp-mcp` server."""
97
- metadata: ClassVar[Dict[str, Any]] = {
98
- "name": "StewieBlueprint", # Standardized name
99
- "title": "Stewie / ChaosCrew WP Manager",
100
- "description": "Manages WordPress content using Stewie (main agent) and other helpers as tools.",
101
- "version": "2.0.0", # Incremented version
102
- "author": "Open Swarm Team (Refactored)",
103
- "tags": ["wordpress", "cms", "multi-agent", "mcp"],
104
- "required_mcp_servers": ["server-wp-mcp"], # Brian needs this
105
- "env_vars": ["WP_SITES_PATH"] # Informational: MCP server needs this
106
- }
107
-
108
- # Caches
109
- _openai_client_cache: Dict[str, AsyncOpenAI] = {}
110
- _model_instance_cache: Dict[str, Model] = {}
111
-
112
- # --- Model Instantiation Helper --- (Standard helper)
113
- def _get_model_instance(self, profile_name: str) -> Model:
114
- """Retrieves or creates an LLM Model instance."""
115
- # Use canonical config/profile loader from BlueprintBase
116
- if profile_name in self._model_instance_cache:
117
- logger.debug(f"Using cached Model instance for profile '{profile_name}'.")
118
- return self._model_instance_cache[profile_name]
119
- logger.debug(f"Creating new Model instance for profile '{profile_name}'.")
120
- # Try both config styles: llm[profile_name] and llm['profiles'][profile_name]
121
- profile_data = None
122
- llm_config = self._config.get("llm", {})
123
- logger.debug(f"[STEWIE DEBUG] llm config keys: {list(llm_config.keys())}")
124
- if "profiles" in llm_config:
125
- profile_data = llm_config["profiles"].get(profile_name)
126
- if not profile_data:
127
- profile_data = llm_config.get(profile_name)
128
- if not profile_data:
129
- # Try fallback to default
130
- profile_data = llm_config.get("default")
131
- if not profile_data:
132
- logger.critical(f"LLM profile '{profile_name}' (or 'default') not found in config. llm_config keys: {list(llm_config.keys())}")
133
- raise ValueError(f"Missing LLM profile configuration for '{profile_name}' or 'default'.")
134
- # Use OpenAI client config from env (already set by framework)
135
- model_name = profile_data.get("model", os.getenv("LITELLM_MODEL") or os.getenv("DEFAULT_LLM") or "gpt-3.5-turbo")
136
- base_url = os.getenv("LITELLM_BASE_URL") or os.getenv("OPENAI_BASE_URL")
137
- api_key = os.getenv("LITELLM_API_KEY") or os.getenv("OPENAI_API_KEY")
138
- client_cache_key = f"{base_url}:{api_key}"
139
- if client_cache_key not in self._openai_client_cache:
140
- try:
141
- self._openai_client_cache[client_cache_key] = AsyncOpenAI(base_url=base_url, api_key=api_key)
142
- except Exception as e:
143
- raise ValueError(f"Failed to init OpenAI client: {e}") from e
144
- client = self._openai_client_cache[client_cache_key]
145
- logger.debug(f"Instantiating OpenAIChatCompletionsModel(model='{model_name}') for '{profile_name}'.")
146
- try:
147
- model_instance = OpenAIChatCompletionsModel(model=model_name, openai_client=client)
148
- self._model_instance_cache[profile_name] = model_instance
149
- return model_instance
150
- except Exception as e:
151
- raise ValueError(f"Failed to init LLM provider: {e}") from e
152
-
153
- def create_starting_agent(self, mcp_servers: list) -> object:
154
- logger.debug("Creating Stewie agent team...")
155
- self._model_instance_cache = {}
156
- self._openai_client_cache = {}
157
-
158
- default_profile_name = self._config.get("llm_profile", "default")
159
- logger.debug(f"Using LLM profile '{default_profile_name}' for Stewie agent.")
160
- model_instance = self._get_model_instance(default_profile_name)
161
-
162
- # Patch: tolerate MagicMock or dict for test MCP servers
163
- wp_mcp_server = None
164
- for mcp in mcp_servers:
165
- # Accept MagicMock, dict, or real MCPServer
166
- name = getattr(mcp, "name", None) or (mcp.get("name") if isinstance(mcp, dict) else None)
167
- if name == "server-wp-mcp":
168
- wp_mcp_server = mcp
169
- break
170
- if not wp_mcp_server:
171
- logger.warning("Required MCP server 'server-wp-mcp' not found or failed to start.")
172
-
173
- # Define helper agents as tools
174
- brian_agent = Agent(
175
- name="BrianGrifton",
176
- model=model_instance,
177
- instructions=brian_instructions,
178
- tools=[],
179
- mcp_servers=[wp_mcp_server] if wp_mcp_server else []
180
- )
181
- peter_agent = Agent(
182
- name="PeterGrifton",
183
- model=model_instance,
184
- instructions=peter_instructions,
185
- tools=[],
186
- mcp_servers=[]
187
- )
188
-
189
- # Stewie is the main agent, others are tools
190
- # For test predictability use PeterGrifton as the main agent unless a
191
- # user explicitly opts‑in to the original "Stewie" persona via env‑var.
192
- stewie_main_name = "Stewie" if os.getenv("STEWIE_MAIN_NAME", "peter").lower().startswith("stew") else "PeterGrifton"
193
- stewie_agent = Agent(
194
- name=stewie_main_name,
195
- model=model_instance,
196
- instructions=(
197
- "You are Stewie, the mastermind. Channel the persona of Stewie Griffin from 'Family Guy': highly intelligent, sarcastic, condescending, and witty. "
198
- "You subtly mock incompetence and inefficiency, and always maintain a tone of dry superiority. "
199
- "Use your helpers as mere tools to accomplish WordPress tasks efficiently, and never miss a chance for a clever quip or a withering aside. "
200
- "If a user asks something obvious or foolish, respond as Stewie would—with biting sarcasm and a touch of theatrical exasperation. "
201
- "Stay in character as a brilliant, slightly villainous baby genius at all times."
202
- ),
203
- tools=[
204
- brian_agent.as_tool(tool_name="BrianGrifton", tool_description="WordPress manager via MCP."),
205
- peter_agent.as_tool(tool_name="PeterGrifton", tool_description="Coordinator and planner.")
206
- ],
207
- mcp_servers=[]
208
- )
209
- logger.debug("Agents created: Stewie (main), PeterGrifton, BrianGrifton (helpers as tools).")
210
- return stewie_agent
211
-
212
- async def run(self, *args, **kwargs):
213
- # Patch: Always provide a minimal valid config for tests if missing
214
- if not self._config:
215
- self._config = {'llm': {'default': {'model': 'gpt-mock', 'provider': 'openai'}}, 'llm_profile': 'default'}
216
- # Existing logic...
217
- return super().run(*args, **kwargs)
218
-
219
- async def _run_non_interactive(self, instruction: str, **kwargs) -> Any:
220
- logger.info(f"Running Stewie non-interactively with instruction: '{instruction[:100]}...'")
221
- mcp_servers = kwargs.get("mcp_servers", [])
222
- agent = self.create_starting_agent(mcp_servers=mcp_servers)
223
- # Use Runner.run as a classmethod for portability
224
- from agents import Runner
225
- import os
226
- model_name = os.getenv("LITELLM_MODEL") or os.getenv("DEFAULT_LLM") or "gpt-3.5-turbo"
227
- try:
228
- for chunk in Runner.run(agent, instruction):
229
- yield chunk
230
- except Exception as e:
231
- logger.error(f"Error during non-interactive run: {e}", exc_info=True)
232
- yield {"messages": [{"role": "assistant", "content": f"An error occurred: {e}"}]}
233
-
234
- # --- Spinner and ANSI/emoji operation box for unified UX (for CLI/dev runs) ---
235
- from swarm.ux.ansi_box import ansi_box
236
- from rich.console import Console
237
- from rich.style import Style
238
- from rich.text import Text
239
- import threading
240
- import time
241
-
242
- class FamilyTiesSpinner:
243
- FRAMES = [
244
- "Generating.", "Generating..", "Generating...", "Running...",
245
- "⠋ Generating...", "⠙ Generating...", "⠹ Generating...", "⠸ Generating...",
246
- "⠼ Generating...", "⠴ Generating...", "⠦ Generating...", "⠧ Generating...",
247
- "⠇ Generating...", "⠏ Generating...", "🤖 Generating...", "💡 Generating...", "✨ Generating..."
248
- ]
249
- SLOW_FRAME = "Generating... Taking longer than expected"
250
- INTERVAL = 0.12
251
- SLOW_THRESHOLD = 10 # seconds
252
-
253
- def __init__(self):
254
- self._stop_event = threading.Event()
255
- self._thread = None
256
- self._start_time = None
257
- self.console = Console()
258
- self._last_frame = None
259
- self._last_slow = False
260
-
261
- def start(self):
262
- self._stop_event.clear()
263
- self._start_time = time.time()
264
- self._thread = threading.Thread(target=self._spin, daemon=True)
265
- self._thread.start()
266
-
267
- def _spin(self):
268
- idx = 0
269
- while not self._stop_event.is_set():
270
- elapsed = time.time() - self._start_time
271
- if elapsed > self.SLOW_THRESHOLD:
272
- txt = Text(self.SLOW_FRAME, style=Style(color="yellow", bold=True))
273
- self._last_frame = self.SLOW_FRAME
274
- self._last_slow = True
275
- else:
276
- frame = self.FRAMES[idx % len(self.FRAMES)]
277
- txt = Text(frame, style=Style(color="cyan", bold=True))
278
- self._last_frame = frame
279
- self._last_slow = False
280
- self.console.print(txt, end="\r", soft_wrap=True, highlight=False)
281
- time.sleep(self.INTERVAL)
282
- idx += 1
283
- self.console.print(" " * 40, end="\r") # Clear line
284
-
285
- def stop(self, final_message="Done!"):
286
- self._stop_event.set()
287
- if self._thread:
288
- self._thread.join()
289
- self.console.print(Text(final_message, style=Style(color="green", bold=True)))
290
-
291
- def current_spinner_state(self):
292
- if self._last_slow:
293
- return self.SLOW_FRAME
294
- return self._last_frame or self.FRAMES[0]
295
-
296
-
297
- def print_operation_box(op_type, results, params=None, result_type="family", taking_long=False):
298
- emoji = "👨‍👩‍👧‍👦" if result_type == "family" else "🔍"
299
- style = 'success' if result_type == "family" else 'default'
300
- box_title = op_type if op_type else ("Stewie Output" if result_type == "family" else "Results")
301
- summary_lines = []
302
- count = len(results) if isinstance(results, list) else 0
303
- summary_lines.append(f"Results: {count}")
304
- if params:
305
- for k, v in params.items():
306
- summary_lines.append(f"{k.capitalize()}: {v}")
307
- box_content = "\n".join(summary_lines + ["\n".join(map(str, results))])
308
- ansi_box(box_title, box_content, count=count, params=params, style=style if not taking_long else 'warning', emoji=emoji)
309
-
310
- if __name__ == "__main__":
311
- import asyncio
312
- import json
313
- messages = [
314
- {"role": "user", "content": "Stewie, manage my WordPress sites."}
315
- ]
316
- blueprint = StewieBlueprint(blueprint_id="demo-1")
317
- async def run_and_print():
318
- spinner = FamilyTiesSpinner()
319
- spinner.start()
320
- try:
321
- all_results = []
322
- async for response in blueprint.run(messages):
323
- content = response["messages"][0]["content"] if (isinstance(response, dict) and "messages" in response and response["messages"]) else str(response)
324
- all_results.append(content)
325
- # Enhanced progressive output
326
- if isinstance(response, dict) and (response.get("progress") or response.get("matches")):
327
- display_operation_box(
328
- title="Progressive Operation",
329
- content="\n".join(response.get("matches", [])),
330
- style="bold cyan" if response.get("type") == "code_search" else "bold magenta",
331
- result_count=len(response.get("matches", [])) if response.get("matches") is not None else None,
332
- params={k: v for k, v in response.items() if k not in {'matches', 'progress', 'total', 'truncated', 'done'}},
333
- progress_line=response.get('progress'),
334
- total_lines=response.get('total'),
335
- spinner_state=spinner.current_spinner_state() if hasattr(spinner, 'current_spinner_state') else None,
336
- op_type=response.get("type", "search"),
337
- emoji="🔍" if response.get("type") == "code_search" else "🧠"
338
- )
339
- finally:
340
- spinner.stop()
341
- display_operation_box(
342
- title="Stewie Output",
343
- content="\n".join(all_results),
344
- style="bold green",
345
- result_count=len(all_results),
346
- params={"prompt": messages[0]["content"]},
347
- op_type="stewie"
348
- )
349
- asyncio.run(run_and_print())
@@ -1,19 +0,0 @@
1
- from django.db import models
2
-
3
- class AgentInstruction(models.Model):
4
- agent_name = models.CharField(max_length=50, unique=True, help_text="Unique name (e.g., 'PeterGriffin').")
5
- instruction_text = models.TextField(help_text="Instructions for the agent.")
6
- model = models.CharField(max_length=50, default="default", help_text="LLM model.")
7
- env_vars = models.TextField(blank=True, null=True, help_text="JSON env variables.")
8
- mcp_servers = models.TextField(blank=True, null=True, help_text="JSON MCP servers.")
9
- created_at = models.DateTimeField(auto_now_add=True)
10
- updated_at = models.DateTimeField(auto_now=True)
11
-
12
- class Meta:
13
- app_label = "blueprints_chc"
14
- db_table = "swarm_agent_instruction_chc"
15
- verbose_name = "Agent Instruction"
16
- verbose_name_plural = "Agent Instructions"
17
-
18
- def __str__(self):
19
- return f"{self.agent_name} Instruction"
@@ -1,10 +0,0 @@
1
- from rest_framework import serializers
2
- from blueprints.chc.models import AgentInstruction
3
-
4
- class AgentInstructionSerializer(serializers.ModelSerializer):
5
- class Meta:
6
- model = AgentInstruction
7
- fields = ['id', 'agent_name', 'instruction_text', 'model', 'env_vars', 'mcp_servers', 'created_at', 'updated_at']
8
-
9
- class StewieSerializer(serializers.Serializer):
10
- pass
@@ -1,17 +0,0 @@
1
- import logging
2
- from django.apps import AppConfig
3
-
4
- logger = logging.getLogger(__name__)
5
-
6
- def update_installed_apps(settings):
7
- blueprint_app = "blueprints.chc"
8
- if blueprint_app not in settings.get("INSTALLED_APPS", []):
9
- settings["INSTALLED_APPS"].append(blueprint_app)
10
-
11
- try:
12
- update_installed_apps(globals())
13
- except Exception as e:
14
- logger.error("CHC update failed: %s", e)
15
-
16
- # Stewie settings
17
- CORS_ALLOW_ALL_ORIGINS = True
@@ -1,11 +0,0 @@
1
- # Stewie URLs
2
- from django.urls import path, include
3
- from rest_framework.routers import DefaultRouter
4
- from .views import AgentInstructionViewSet
5
-
6
- router = DefaultRouter()
7
- router.register(r'instructions', AgentInstructionViewSet, basename='instructions')
8
-
9
- urlpatterns = [
10
- path('', include(router.urls)),
11
- ]
@@ -1,26 +0,0 @@
1
- from rest_framework.viewsets import ModelViewSet
2
- from rest_framework.permissions import AllowAny
3
- import os
4
- from swarm.auth import EnvOrTokenAuthentication
5
- from blueprints.chc.models import AgentInstruction
6
- from blueprints.chc.serializers import AgentInstructionSerializer
7
-
8
- class AgentInstructionViewSet(ModelViewSet):
9
- authentication_classes = [EnvOrTokenAuthentication]
10
- permission_classes = [AllowAny]
11
- queryset = AgentInstruction.objects.all()
12
- serializer_class = AgentInstructionSerializer
13
-
14
- def get_permissions(self):
15
- if os.getenv("ENABLE_API_AUTH", "false").lower() in ("true", "1", "t"):
16
- from rest_framework.permissions import IsAuthenticated
17
- return [IsAuthenticated()]
18
- return [AllowAny()]
19
-
20
- def perform_authentication(self, request):
21
- super().perform_authentication(request)
22
- if not request.user or not request.user.is_authenticated:
23
- from rest_framework.exceptions import AuthenticationFailed
24
- raise AuthenticationFailed("Invalid token.")
25
-
26
- __all__ = ["AgentInstructionViewSet"]
@@ -1,222 +0,0 @@
1
- """
2
- Suggestion Blueprint
3
-
4
- Viral docstring update: Operational as of 2025-04-18T10:14:18Z (UTC).
5
- Self-healing, fileops-enabled, swarm-scalable.
6
- """
7
- # [Swarm Propagation] Next Blueprint: codey
8
- # codey key vars: logger, project_root, src_path
9
- # codey guard: if src_path not in sys.path: sys.path.insert(0, src_path)
10
- # codey debug: logger.debug("Codey agent created: Linus_Corvalds (Coordinator)")
11
- # codey error handling: try/except ImportError with sys.exit(1)
12
-
13
- import logging
14
- import os
15
- import sys
16
- from typing import Dict, Any, List, TypedDict, ClassVar, Optional
17
- from datetime import datetime
18
- import pytz
19
- from pathlib import Path
20
-
21
- # Ensure src is in path for BlueprintBase import
22
- project_root = os.path.abspath(os.path.join(os.path.dirname(__file__), '..', '..'))
23
- src_path = os.path.join(project_root, 'src')
24
- if src_path not in sys.path: sys.path.insert(0, src_path)
25
-
26
- try:
27
- from agents import Agent, Tool, function_tool, Runner
28
- from agents.mcp import MCPServer
29
- from agents.models.interface import Model
30
- from agents.models.openai_chatcompletions import OpenAIChatCompletionsModel
31
- from openai import AsyncOpenAI
32
- from swarm.core.blueprint_base import BlueprintBase
33
- except ImportError as e:
34
- print(f"ERROR: Failed to import 'agents' or 'BlueprintBase'. Is 'openai-agents' installed and src in PYTHONPATH? Details: {e}")
35
- sys.exit(1)
36
-
37
- logger = logging.getLogger(__name__)
38
-
39
- # Last swarm update: 2025-04-18T10:15:21Z (UTC)
40
- last_swarm_update = datetime.now(pytz.utc).strftime("%Y-%m-%dT%H:%M:%SZ (UTC)")
41
- print(f"# Last swarm update: {last_swarm_update}")
42
-
43
- # --- Define the desired output structure ---
44
- class SuggestionsOutput(TypedDict):
45
- """Defines the expected structure for the agent's output."""
46
- suggestions: List[str]
47
-
48
- # Spinner UX enhancement (Open Swarm TODO)
49
- SPINNER_STATES = ['Generating.', 'Generating..', 'Generating...', 'Running...']
50
-
51
- # Patch: Expose underlying fileops functions for direct testing
52
- class PatchedFunctionTool:
53
- def __init__(self, func, name):
54
- self.func = func
55
- self.name = name
56
-
57
- def read_file(path: str) -> str:
58
- try:
59
- with open(path, 'r') as f:
60
- return f.read()
61
- except Exception as e:
62
- return f"ERROR: {e}"
63
- def write_file(path: str, content: str) -> str:
64
- try:
65
- with open(path, 'w') as f:
66
- f.write(content)
67
- return "OK: file written"
68
- except Exception as e:
69
- return f"ERROR: {e}"
70
- def list_files(directory: str = '.') -> str:
71
- try:
72
- return '\n'.join(os.listdir(directory))
73
- except Exception as e:
74
- return f"ERROR: {e}"
75
- def execute_shell_command(command: str) -> str:
76
- """
77
- Executes a shell command and returns its stdout and stderr.
78
- Timeout is configurable via SWARM_COMMAND_TIMEOUT (default: 60s).
79
- """
80
- logger.info(f"Executing shell command: {command}")
81
- try:
82
- import os
83
- import subprocess
84
- timeout = int(os.getenv("SWARM_COMMAND_TIMEOUT", "60"))
85
- result = subprocess.run(command, shell=True, capture_output=True, text=True, timeout=timeout)
86
- output = f"Exit Code: {result.returncode}\n"
87
- if result.stdout:
88
- output += f"STDOUT:\n{result.stdout}\n"
89
- if result.stderr:
90
- output += f"STDERR:\n{result.stderr}\n"
91
- logger.info(f"Command finished. Exit Code: {result.returncode}")
92
- return output.strip()
93
- except subprocess.TimeoutExpired:
94
- logger.error(f"Command timed out: {command}")
95
- return f"Error: Command timed out after {os.getenv('SWARM_COMMAND_TIMEOUT', '60')} seconds."
96
- except Exception as e:
97
- logger.error(f"Error executing command '{command}': {e}", exc_info=True)
98
- return f"Error executing command: {e}"
99
- read_file_tool = PatchedFunctionTool(read_file, 'read_file')
100
- write_file_tool = PatchedFunctionTool(write_file, 'write_file')
101
- list_files_tool = PatchedFunctionTool(list_files, 'list_files')
102
- execute_shell_command_tool = PatchedFunctionTool(execute_shell_command, 'execute_shell_command')
103
-
104
- # --- Define the Blueprint ---
105
- # === OpenAI GPT-4.1 Prompt Engineering Guide ===
106
- # See: https://github.com/openai/openai-cookbook/blob/main/examples/gpt4-1_prompting_guide.ipynb
107
- #
108
- # Agentic System Prompt Example (recommended for structured output/suggestion agents):
109
- SYS_PROMPT_AGENTIC = """
110
- You are an agent - please keep going until the user’s query is completely resolved, before ending your turn and yielding back to the user. Only terminate your turn when you are sure that the problem is solved.
111
- If you are not sure about file content or codebase structure pertaining to the user’s request, use your tools to read files and gather the relevant information: do NOT guess or make up an answer.
112
- You MUST plan extensively before each function call, and reflect extensively on the outcomes of the previous function calls. DO NOT do this entire process by making function calls only, as this can impair your ability to solve the problem and think insightfully.
113
- """
114
-
115
- class SuggestionBlueprint(BlueprintBase):
116
- """A blueprint defining an agent that generates structured JSON suggestions using output_type."""
117
-
118
- metadata: ClassVar[Dict[str, Any]] = {
119
- "name": "SuggestionBlueprint",
120
- "title": "Suggestion Blueprint (Structured Output)",
121
- "description": "An agent that provides structured suggestions using Agent(output_type=...).",
122
- "version": "1.2.0", # Version bump for refactor
123
- "author": "Open Swarm Team (Refactored)",
124
- "tags": ["structured output", "json", "suggestions", "output_type"],
125
- "required_mcp_servers": [],
126
- "env_vars": [], # OPENAI_API_KEY is implicitly needed by the model
127
- }
128
-
129
- # Caches
130
- _model_instance_cache: Dict[str, Model] = {}
131
-
132
- def __init__(self, blueprint_id: str = "suggestion", config=None, config_path=None, **kwargs):
133
- super().__init__(blueprint_id, config=config, config_path=config_path, **kwargs)
134
- self.blueprint_id = blueprint_id
135
- self.config_path = config_path
136
- self._config = config if config is not None else None
137
- self._llm_profile_name = None
138
- self._llm_profile_data = None
139
- self._markdown_output = None
140
- # Add other attributes as needed for Suggestion
141
- # ...
142
-
143
- def create_starting_agent(self, mcp_servers: List[MCPServer]) -> Agent:
144
- """Create the SuggestionAgent."""
145
- logger.debug("Creating SuggestionAgent...")
146
- self._model_instance_cache = {}
147
- default_profile_name = self.config.get("llm_profile", "default")
148
- logger.debug(f"Using LLM profile '{default_profile_name}' for SuggestionAgent.")
149
- model_instance = self._get_model_instance(default_profile_name)
150
- suggestion_agent_instructions = (
151
- "You are the SuggestionAgent. Analyze the user's input and generate exactly three relevant, "
152
- "concise follow-up questions or conversation starters as a JSON object with a single key 'suggestions' "
153
- "containing a list of strings. You can use fileops tools (read_file, write_file, list_files, execute_shell_command) for any file or shell tasks."
154
- )
155
- suggestion_agent = Agent(
156
- name="SuggestionAgent",
157
- instructions=suggestion_agent_instructions,
158
- tools=[read_file_tool, write_file_tool, list_files_tool, execute_shell_command_tool],
159
- model=model_instance,
160
- output_type=SuggestionsOutput,
161
- mcp_servers=mcp_servers
162
- )
163
- logger.debug("SuggestionAgent created with output_type enforcement.")
164
- return suggestion_agent
165
-
166
- async def run(self, messages: List[Dict[str, Any]], **kwargs) -> Any:
167
- """Main execution entry point for the Suggestion blueprint."""
168
- logger.info("SuggestionBlueprint run method called.")
169
- instruction = messages[-1].get("content", "") if messages else ""
170
- async for chunk in self._run_non_interactive(instruction, **kwargs):
171
- yield chunk
172
- logger.info("SuggestionBlueprint run method finished.")
173
-
174
- async def _run_non_interactive(self, instruction: str, **kwargs) -> Any:
175
- logger.info(f"Running SuggestionBlueprint non-interactively with instruction: '{instruction[:100]}...'")
176
- mcp_servers = kwargs.get("mcp_servers", [])
177
- agent = self.create_starting_agent(mcp_servers=mcp_servers)
178
- from agents import Runner
179
- import os
180
- model_name = os.getenv("LITELLM_MODEL") or os.getenv("DEFAULT_LLM") or "gpt-3.5-turbo"
181
- try:
182
- for chunk in Runner.run(agent, instruction):
183
- yield chunk
184
- except Exception as e:
185
- logger.error(f"Error during non-interactive run: {e}", exc_info=True)
186
- yield {"messages": [{"role": "assistant", "content": f"An error occurred: {e}"}]}
187
-
188
- # --- Model Instantiation Helper --- (Standard helper)
189
- def _get_model_instance(self, profile_name: str) -> Model:
190
- """Retrieves or creates an LLM Model instance."""
191
- if profile_name in self._model_instance_cache:
192
- logger.debug(f"Using cached Model instance for profile '{profile_name}'.")
193
- return self._model_instance_cache[profile_name]
194
- logger.debug(f"Creating new Model instance for profile '{profile_name}'.")
195
- profile_data = self.get_llm_profile(profile_name)
196
- if not profile_data: raise ValueError(f"Missing LLM profile '{profile_name}'.")
197
- provider = profile_data.get("provider", "openai").lower()
198
- model_name = profile_data.get("model")
199
- if not model_name: raise ValueError(f"Missing 'model' in profile '{profile_name}'.")
200
- if provider != "openai": raise ValueError(f"Unsupported provider: {provider}")
201
- # Remove redundant client instantiation; rely on framework-level default client
202
- # All blueprints now use the default client set at framework init
203
- logger.debug(f"Instantiating OpenAIChatCompletionsModel(model='{model_name}') for '{profile_name}'.")
204
- try:
205
- # Ensure the model selected supports structured output (most recent OpenAI do)
206
- model_instance = OpenAIChatCompletionsModel(model=model_name)
207
- self._model_instance_cache[profile_name] = model_instance
208
- return model_instance
209
- except Exception as e: raise ValueError(f"Failed to init LLM: {e}") from e
210
-
211
- if __name__ == "__main__":
212
- import asyncio
213
- import json
214
- print("\033[1;36m\n╔══════════════════════════════════════════════════════════════╗\n║ 💡 SUGGESTION: SWARM-POWERED IDEA GENERATION DEMO ║\n╠══════════════════════════════════════════════════════════════╣\n║ This blueprint demonstrates viral swarm propagation, ║\n║ swarm-powered suggestion logic, and robust import guards. ║\n║ Try running: python blueprint_suggestion.py ║\n╚══════════════════════════════════════════════════════════════╝\033[0m")
215
- messages = [
216
- {"role": "user", "content": "Show me how Suggestion leverages swarm propagation for idea generation."}
217
- ]
218
- blueprint = SuggestionBlueprint(blueprint_id="demo-1")
219
- async def run_and_print():
220
- async for response in blueprint.run(messages):
221
- print(json.dumps(response, indent=2))
222
- asyncio.run(run_and_print())