open-swarm 0.1.1744936173__py3-none-any.whl → 0.1.1744936234__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.
- {open_swarm-0.1.1744936173.dist-info → open_swarm-0.1.1744936234.dist-info}/METADATA +1 -1
- {open_swarm-0.1.1744936173.dist-info → open_swarm-0.1.1744936234.dist-info}/RECORD +16 -16
- swarm/blueprints/digitalbutlers/blueprint_digitalbutlers.py +28 -0
- swarm/blueprints/divine_code/blueprint_divine_code.py +26 -0
- swarm/blueprints/django_chat/blueprint_django_chat.py +15 -4
- swarm/blueprints/echocraft/blueprint_echocraft.py +9 -2
- swarm/blueprints/family_ties/blueprint_family_ties.py +28 -0
- swarm/blueprints/gaggle/blueprint_gaggle.py +117 -15
- swarm/blueprints/monkai_magic/blueprint_monkai_magic.py +10 -0
- swarm/blueprints/nebula_shellz/blueprint_nebula_shellz.py +47 -29
- swarm/blueprints/omniplex/blueprint_omniplex.py +21 -0
- swarm/blueprints/rue_code/blueprint_rue_code.py +24 -25
- swarm/blueprints/suggestion/blueprint_suggestion.py +35 -12
- {open_swarm-0.1.1744936173.dist-info → open_swarm-0.1.1744936234.dist-info}/WHEEL +0 -0
- {open_swarm-0.1.1744936173.dist-info → open_swarm-0.1.1744936234.dist-info}/entry_points.txt +0 -0
- {open_swarm-0.1.1744936173.dist-info → open_swarm-0.1.1744936234.dist-info}/licenses/LICENSE +0 -0
@@ -1,6 +1,6 @@
|
|
1
1
|
Metadata-Version: 2.4
|
2
2
|
Name: open-swarm
|
3
|
-
Version: 0.1.
|
3
|
+
Version: 0.1.1744936234
|
4
4
|
Summary: Open Swarm: Orchestrating AI Agent Swarms with Django
|
5
5
|
Project-URL: Homepage, https://github.com/yourusername/open-swarm
|
6
6
|
Project-URL: Documentation, https://github.com/yourusername/open-swarm/blob/main/README.md
|
@@ -16,34 +16,34 @@ swarm/agent/__init__.py,sha256=YESGu_UXEBxrlQwghodUMN0vmXZDwWMU7DclCUvoklA,104
|
|
16
16
|
swarm/blueprints/README.md,sha256=tsngbSB9N0tILcz_m1OGAjyKZQYlGTN-i5e5asq1GbE,8478
|
17
17
|
swarm/blueprints/chatbot/blueprint_chatbot.py,sha256=a5-gIyDvRtNgbyfviD9Hua9r5NjOQh1lOafIG2a6kiI,7520
|
18
18
|
swarm/blueprints/chatbot/templates/chatbot/chatbot.html,sha256=REFnqNg0EHsXxAUfaCJe1YgOKiV_umBXuC6y8veF5CU,1568
|
19
|
-
swarm/blueprints/digitalbutlers/blueprint_digitalbutlers.py,sha256=
|
19
|
+
swarm/blueprints/digitalbutlers/blueprint_digitalbutlers.py,sha256=bQ0h_oC7TBbwjXhlSDGgjsnePb8cRcCnft2CggZuLY0,11301
|
20
20
|
swarm/blueprints/divine_code/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
21
21
|
swarm/blueprints/divine_code/apps.py,sha256=k615JHdfOuo_GwfVbC7ah8X9OblkAL2XWm9aLBjmMyY,306
|
22
|
-
swarm/blueprints/divine_code/blueprint_divine_code.py,sha256=
|
22
|
+
swarm/blueprints/divine_code/blueprint_divine_code.py,sha256=p4A9RhvBrWy6OKFNWCxKUqQAmkc49xcSh5V0FGiZ50k,14994
|
23
23
|
swarm/blueprints/django_chat/apps.py,sha256=rn1Eu11c4zZ6DYZeFb6AkCDMoM_dcQTzeNwW-IxXpCI,200
|
24
|
-
swarm/blueprints/django_chat/blueprint_django_chat.py,sha256=
|
24
|
+
swarm/blueprints/django_chat/blueprint_django_chat.py,sha256=kaxR7mV6mYW3HQTLO36xpCP2jhbj_sb4VKnMgE9GiWo,3716
|
25
25
|
swarm/blueprints/django_chat/urls.py,sha256=TTTF3pgymvCYbuxpwi4WRBPv8ftQNH4pEoURT8sEVAg,147
|
26
26
|
swarm/blueprints/django_chat/views.py,sha256=MUKjXXjXsq8jMZtAb4RR9g2mEYrwFemN6Bqxpeyi7p4,1299
|
27
27
|
swarm/blueprints/django_chat/templates/django_chat/django_chat_webpage.html,sha256=wAEOI4Wg0JJ8drXaOcr2Pel6lW3JSHmyIpbocLS5tI8,1649
|
28
|
-
swarm/blueprints/echocraft/blueprint_echocraft.py,sha256=
|
28
|
+
swarm/blueprints/echocraft/blueprint_echocraft.py,sha256=Bv9ceqPQgPtWDHtmZejJn9YyXPJOA4uUwXnQpBcG52g,3145
|
29
29
|
swarm/blueprints/family_ties/apps.py,sha256=EjV7AxDNsLM4gsLr_qMEiLAVbERuo1ZsdU9vPtOEYAY,287
|
30
|
-
swarm/blueprints/family_ties/blueprint_family_ties.py,sha256=
|
30
|
+
swarm/blueprints/family_ties/blueprint_family_ties.py,sha256=Pkqgf7oF5Ag8YddeeLbGPreb4r1YdGSYSsOQmZ18VIM,9462
|
31
31
|
swarm/blueprints/family_ties/models.py,sha256=C3_okdVVYuu9xOpoKRsaLoGrM2775cS_cU4UKYAkJ9s,903
|
32
32
|
swarm/blueprints/family_ties/serializers.py,sha256=kH3T6OgXjF534bO3gfAUr6GpXZ5Jx0BQkK58nvuEcqA,325
|
33
33
|
swarm/blueprints/family_ties/settings.py,sha256=5zcVsq7ny3GLWcJnOplZW4fMFNtyC3ba0ZOESRD2gh4,425
|
34
34
|
swarm/blueprints/family_ties/urls.py,sha256=awRZHb1gb1p3I6YZzfKMGSydd6kYPTLgax2jZ1ocS4U,294
|
35
35
|
swarm/blueprints/family_ties/views.py,sha256=FbPkDNlFEixtRFbSpkr51IyJ28FRkXa1W5xyO_KeXH0,1081
|
36
36
|
swarm/blueprints/flock/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
37
|
-
swarm/blueprints/gaggle/blueprint_gaggle.py,sha256=
|
37
|
+
swarm/blueprints/gaggle/blueprint_gaggle.py,sha256=4H_eJQEzmw56IiadhMa8dYqHeiY9ubJiK5ziffo01Zs,14151
|
38
38
|
swarm/blueprints/mcp_demo/blueprint_mcp_demo.py,sha256=eUu5_BvLwVSdWiEonXWKuN7YgKsqz04JB_KbMPowryc,6599
|
39
39
|
swarm/blueprints/messenger/templates/messenger/messenger.html,sha256=izuFtFn40Gm7M4gSUAUT5CIezjBjmNv2w4_fwSlv7VA,2323
|
40
40
|
swarm/blueprints/mission_improbable/blueprint_mission_improbable.py,sha256=N4Tw0laErP4eCJM103XOaVrqbFNKZRUG1Bpze8g79MI,12753
|
41
|
-
swarm/blueprints/monkai_magic/blueprint_monkai_magic.py,sha256=
|
42
|
-
swarm/blueprints/nebula_shellz/blueprint_nebula_shellz.py,sha256=
|
43
|
-
swarm/blueprints/omniplex/blueprint_omniplex.py,sha256=
|
41
|
+
swarm/blueprints/monkai_magic/blueprint_monkai_magic.py,sha256=cx2hPbYcttOcvC4jfb6tExSUKiL4GMOHxuqzLtuSlso,14235
|
42
|
+
swarm/blueprints/nebula_shellz/blueprint_nebula_shellz.py,sha256=d_b-5doQVLUMfoFMLeQfumVl09hr91JkuGTonLtrqi4,9917
|
43
|
+
swarm/blueprints/omniplex/blueprint_omniplex.py,sha256=wbxTux_98dFjUSjzJNIhLDJMNlVfAfSUmlJjTJ9VQFs,12670
|
44
44
|
swarm/blueprints/rue_code/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
45
|
-
swarm/blueprints/rue_code/blueprint_rue_code.py,sha256=
|
46
|
-
swarm/blueprints/suggestion/blueprint_suggestion.py,sha256=
|
45
|
+
swarm/blueprints/rue_code/blueprint_rue_code.py,sha256=28Eb_SDsvlnDC3SLNYHrKBpD6izTz53U-jqfZ6nqpto,15417
|
46
|
+
swarm/blueprints/suggestion/blueprint_suggestion.py,sha256=hB7SWedDcc97LzVK56qEe7IufK_p5Ze-9H5TxXREGsE,7112
|
47
47
|
swarm/blueprints/unapologetic_press/blueprint_unapologetic_press.py,sha256=e1-HpSHNp1PJAcb3-6sI1kE7KeJRQ2lGTUJPXYjvaY4,17648
|
48
48
|
swarm/blueprints/whiskeytango_foxtrot/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
49
49
|
swarm/blueprints/whiskeytango_foxtrot/apps.py,sha256=V1QKvyb2Vz-EtDNhhNe4tw2W9LYhNDuiaIq_fAU4ilw,334
|
@@ -252,8 +252,8 @@ swarm/views/message_views.py,sha256=sDUnXyqKXC8WwIIMAlWf00s2_a2T9c75Na5FvYMJwBM,
|
|
252
252
|
swarm/views/model_views.py,sha256=aAbU4AZmrOTaPeKMWtoKK7FPYHdaN3Zbx55JfKzYTRY,2937
|
253
253
|
swarm/views/utils.py,sha256=geX3Z5ZDKFYyXYBMilc-4qgOSjhujK3AfRtvbXgFpXk,3643
|
254
254
|
swarm/views/web_views.py,sha256=ExQQeJpZ8CkLZQC_pXKOOmdnEy2qR3wEBP4LLp27DPU,7404
|
255
|
-
open_swarm-0.1.
|
256
|
-
open_swarm-0.1.
|
257
|
-
open_swarm-0.1.
|
258
|
-
open_swarm-0.1.
|
259
|
-
open_swarm-0.1.
|
255
|
+
open_swarm-0.1.1744936234.dist-info/METADATA,sha256=EVV17kQ_iNn0Xmnk7_VkMyLPBIWlbD08R6eDk3xQjko,13678
|
256
|
+
open_swarm-0.1.1744936234.dist-info/WHEEL,sha256=qtCwoSJWgHk21S1Kb4ihdzI2rlJ1ZKaIurTj_ngOhyQ,87
|
257
|
+
open_swarm-0.1.1744936234.dist-info/entry_points.txt,sha256=z1UIVRRhri-V-hWxFkDEYu0SZPUIsVO4KpDaodgcFzU,125
|
258
|
+
open_swarm-0.1.1744936234.dist-info/licenses/LICENSE,sha256=BU9bwRlnOt_JDIb6OT55Q4leLZx9RArDLTFnlDIrBEI,1062
|
259
|
+
open_swarm-0.1.1744936234.dist-info/RECORD,,
|
@@ -8,6 +8,8 @@ project_root = os.path.abspath(os.path.join(os.path.dirname(__file__), '..', '..
|
|
8
8
|
src_path = os.path.join(project_root, 'src')
|
9
9
|
if src_path not in sys.path: sys.path.insert(0, src_path)
|
10
10
|
|
11
|
+
from typing import Optional
|
12
|
+
from pathlib import Path
|
11
13
|
try:
|
12
14
|
from agents import Agent, Tool, function_tool, Runner # Added Runner
|
13
15
|
from agents.mcp import MCPServer
|
@@ -61,6 +63,9 @@ gutenberg_instructions = (
|
|
61
63
|
|
62
64
|
# --- Define the Blueprint ---
|
63
65
|
class DigitalButlersBlueprint(BlueprintBase):
|
66
|
+
def __init__(self, blueprint_id: str, config_path: Optional[Path] = None, **kwargs):
|
67
|
+
super().__init__(blueprint_id, config_path=config_path, **kwargs)
|
68
|
+
|
64
69
|
"""Blueprint for private web search and home automation using a team of digital butlers."""
|
65
70
|
metadata: ClassVar[Dict[str, Any]] = {
|
66
71
|
"name": "DigitalButlersBlueprint",
|
@@ -178,6 +183,29 @@ class DigitalButlersBlueprint(BlueprintBase):
|
|
178
183
|
logger.debug("Digital Butlers team created: Jeeves (Coordinator), Mycroft (Search), Gutenberg (Home).")
|
179
184
|
return jeeves_agent # Jeeves is the entry point
|
180
185
|
|
186
|
+
async def run(self, messages: List[Dict[str, Any]], **kwargs) -> Any:
|
187
|
+
"""Main execution entry point for the DigitalButlers blueprint."""
|
188
|
+
logger.info("DigitalButlersBlueprint run method called.")
|
189
|
+
instruction = messages[-1].get("content", "") if messages else ""
|
190
|
+
async for chunk in self._run_non_interactive(instruction, **kwargs):
|
191
|
+
yield chunk
|
192
|
+
logger.info("DigitalButlersBlueprint run method finished.")
|
193
|
+
|
194
|
+
async def _run_non_interactive(self, instruction: str, **kwargs) -> Any:
|
195
|
+
logger.info(f"Running DigitalButlers non-interactively with instruction: '{instruction[:100]}...'")
|
196
|
+
mcp_servers = kwargs.get("mcp_servers", [])
|
197
|
+
agent = self.create_starting_agent(mcp_servers=mcp_servers)
|
198
|
+
# Use Runner.run as a classmethod for portability
|
199
|
+
from agents import Runner
|
200
|
+
import os
|
201
|
+
model_name = os.getenv("LITELLM_MODEL") or os.getenv("DEFAULT_LLM") or "gpt-3.5-turbo"
|
202
|
+
try:
|
203
|
+
for chunk in Runner.run(agent, instruction):
|
204
|
+
yield chunk
|
205
|
+
except Exception as e:
|
206
|
+
logger.error(f"Error during non-interactive run: {e}", exc_info=True)
|
207
|
+
yield {"messages": [{"role": "assistant", "content": f"An error occurred: {e}"}]}
|
208
|
+
|
181
209
|
# Standard Python entry point
|
182
210
|
if __name__ == "__main__":
|
183
211
|
DigitalButlersBlueprint.main()
|
@@ -8,6 +8,8 @@ project_root = os.path.abspath(os.path.join(os.path.dirname(__file__), '..', '..
|
|
8
8
|
src_path = os.path.join(project_root, 'src')
|
9
9
|
if src_path not in sys.path: sys.path.insert(0, src_path)
|
10
10
|
|
11
|
+
from typing import Optional
|
12
|
+
from pathlib import Path
|
11
13
|
try:
|
12
14
|
from agents import Agent, Tool, function_tool, Runner
|
13
15
|
from agents.mcp import MCPServer
|
@@ -107,6 +109,9 @@ Available MCP Tools (if provided): sequential-thinking, filesystem.
|
|
107
109
|
|
108
110
|
# --- Define the Blueprint ---
|
109
111
|
class DivineOpsBlueprint(BlueprintBase):
|
112
|
+
def __init__(self, blueprint_id: str, config_path: Optional[Path] = None, **kwargs):
|
113
|
+
super().__init__(blueprint_id, config_path=config_path, **kwargs)
|
114
|
+
|
110
115
|
""" Divine Ops: Streamlined Software Dev & Sysadmin Team Blueprint using openai-agents """
|
111
116
|
metadata: ClassVar[Dict[str, Any]] = {
|
112
117
|
"name": "DivineOpsBlueprint",
|
@@ -214,6 +219,27 @@ class DivineOpsBlueprint(BlueprintBase):
|
|
214
219
|
logger.debug("Divine Ops Team (Zeus & Pantheon) created successfully. Zeus is starting agent.")
|
215
220
|
return zeus_agent
|
216
221
|
|
222
|
+
async def run(self, messages: List[Dict[str, Any]], **kwargs) -> Any:
|
223
|
+
"""Main execution entry point for the DivineOps blueprint."""
|
224
|
+
logger.info("DivineOpsBlueprint run method called.")
|
225
|
+
instruction = messages[-1].get("content", "") if messages else ""
|
226
|
+
async for chunk in self._run_non_interactive(instruction, **kwargs):
|
227
|
+
yield chunk
|
228
|
+
logger.info("DivineOpsBlueprint run method finished.")
|
229
|
+
|
230
|
+
async def _run_non_interactive(self, instruction: str, **kwargs) -> Any:
|
231
|
+
logger.info(f"Running DivineOps non-interactively with instruction: '{instruction[:100]}...'")
|
232
|
+
mcp_servers = kwargs.get("mcp_servers", [])
|
233
|
+
agent = self.create_starting_agent(mcp_servers=mcp_servers)
|
234
|
+
runner = Runner(agent=agent)
|
235
|
+
try:
|
236
|
+
final_result = await runner.run(instruction)
|
237
|
+
logger.info(f"Non-interactive run finished. Final Output: {final_result.final_output}")
|
238
|
+
yield { "messages": [ {"role": "assistant", "content": final_result.final_output} ] }
|
239
|
+
except Exception as e:
|
240
|
+
logger.error(f"Error during non-interactive run: {e}", exc_info=True)
|
241
|
+
yield { "messages": [ {"role": "assistant", "content": f"An error occurred: {e}"} ] }
|
242
|
+
|
217
243
|
# Standard Python entry point
|
218
244
|
if __name__ == "__main__":
|
219
245
|
DivineOpsBlueprint.main()
|
@@ -10,11 +10,22 @@ import sys
|
|
10
10
|
import os
|
11
11
|
from typing import Dict, Any, List
|
12
12
|
|
13
|
+
# --- Logging Setup ---
|
14
|
+
def setup_logging():
|
15
|
+
import argparse
|
16
|
+
parser = argparse.ArgumentParser(add_help=False)
|
17
|
+
parser.add_argument('--debug', action='store_true', help='Enable debug logging')
|
18
|
+
args, _ = parser.parse_known_args()
|
19
|
+
loglevel = os.environ.get('LOGLEVEL', None)
|
20
|
+
if args.debug or os.environ.get('SWARM_DEBUG', '0') == '1' or (loglevel and loglevel.upper() == 'DEBUG'):
|
21
|
+
logging.basicConfig(level=logging.DEBUG)
|
22
|
+
else:
|
23
|
+
logging.basicConfig(level=logging.INFO)
|
24
|
+
return args
|
25
|
+
|
26
|
+
args = setup_logging()
|
27
|
+
|
13
28
|
logger = logging.getLogger(__name__)
|
14
|
-
logger.setLevel(logging.DEBUG)
|
15
|
-
handler = logging.StreamHandler(sys.stderr)
|
16
|
-
handler.setFormatter(logging.Formatter("[%(asctime)s] [%(levelname)s] %(name)s:%(lineno)d - %(message)s"))
|
17
|
-
logger.addHandler(handler)
|
18
29
|
|
19
30
|
# Reject CLI execution immediately
|
20
31
|
if __name__ == "__main__":
|
@@ -1,6 +1,7 @@
|
|
1
|
-
|
2
1
|
# --- Content for src/swarm/blueprints/echocraft/blueprint_echocraft.py ---
|
3
2
|
import logging
|
3
|
+
from typing import Optional
|
4
|
+
from pathlib import Path
|
4
5
|
from typing import List, Dict, Any, AsyncGenerator
|
5
6
|
import uuid # Import uuid to generate IDs
|
6
7
|
import time # Import time for timestamp
|
@@ -10,6 +11,9 @@ from swarm.extensions.blueprint.blueprint_base import BlueprintBase
|
|
10
11
|
logger = logging.getLogger(__name__)
|
11
12
|
|
12
13
|
class EchoCraftBlueprint(BlueprintBase):
|
14
|
+
def __init__(self, blueprint_id: str, config_path: Optional[Path] = None, **kwargs):
|
15
|
+
super().__init__(blueprint_id, config_path=config_path, **kwargs)
|
16
|
+
|
13
17
|
"""
|
14
18
|
A simple blueprint that echoes the last user message.
|
15
19
|
Used for testing and demonstrating basic blueprint structure.
|
@@ -27,6 +31,10 @@ class EchoCraftBlueprint(BlueprintBase):
|
|
27
31
|
"""
|
28
32
|
logger.info(f"EchoCraftBlueprint run called with {len(messages)} messages.")
|
29
33
|
|
34
|
+
# Ensure LLM profile is initialized for test compatibility
|
35
|
+
if self._llm_profile_name is None:
|
36
|
+
self._llm_profile_name = self.config.get("llm_profile", "default")
|
37
|
+
|
30
38
|
last_user_message_content = "No user message found."
|
31
39
|
for msg in reversed(messages):
|
32
40
|
if msg.get("role") == "user":
|
@@ -68,4 +76,3 @@ class EchoCraftBlueprint(BlueprintBase):
|
|
68
76
|
# --- End formatting change ---
|
69
77
|
|
70
78
|
logger.info("EchoCraftBlueprint run finished.")
|
71
|
-
|
@@ -8,6 +8,8 @@ project_root = os.path.abspath(os.path.join(os.path.dirname(__file__), '..', '..
|
|
8
8
|
src_path = os.path.join(project_root, 'src')
|
9
9
|
if src_path not in sys.path: sys.path.insert(0, src_path)
|
10
10
|
|
11
|
+
from typing import Optional
|
12
|
+
from pathlib import Path
|
11
13
|
try:
|
12
14
|
from agents import Agent, Tool, function_tool, Runner
|
13
15
|
from agents.mcp import MCPServer
|
@@ -53,6 +55,9 @@ brian_instructions = (
|
|
53
55
|
|
54
56
|
# --- Define the Blueprint ---
|
55
57
|
class FamilyTiesBlueprint(BlueprintBase):
|
58
|
+
def __init__(self, blueprint_id: str, config_path: Optional[Path] = None, **kwargs):
|
59
|
+
super().__init__(blueprint_id, config_path=config_path, **kwargs)
|
60
|
+
|
56
61
|
"""Manages WordPress content with a Peter/Brian agent team using the `server-wp-mcp` server."""
|
57
62
|
metadata: ClassVar[Dict[str, Any]] = {
|
58
63
|
"name": "FamilyTiesBlueprint", # Standardized name
|
@@ -148,5 +153,28 @@ class FamilyTiesBlueprint(BlueprintBase):
|
|
148
153
|
logger.debug("Agents created: PeterGrifton (Coordinator), BrianGrifton (WordPress Manager).")
|
149
154
|
return peter_agent # Peter is the entry point
|
150
155
|
|
156
|
+
async def run(self, messages: List[Dict[str, Any]], **kwargs) -> Any:
|
157
|
+
"""Main execution entry point for the FamilyTies blueprint."""
|
158
|
+
logger.info("FamilyTiesBlueprint run method called.")
|
159
|
+
instruction = messages[-1].get("content", "") if messages else ""
|
160
|
+
async for chunk in self._run_non_interactive(instruction, **kwargs):
|
161
|
+
yield chunk
|
162
|
+
logger.info("FamilyTiesBlueprint run method finished.")
|
163
|
+
|
164
|
+
async def _run_non_interactive(self, instruction: str, **kwargs) -> Any:
|
165
|
+
logger.info(f"Running FamilyTies non-interactively with instruction: '{instruction[:100]}...'")
|
166
|
+
mcp_servers = kwargs.get("mcp_servers", [])
|
167
|
+
agent = self.create_starting_agent(mcp_servers=mcp_servers)
|
168
|
+
# Use Runner.run as a classmethod for portability
|
169
|
+
from agents import Runner
|
170
|
+
import os
|
171
|
+
model_name = os.getenv("LITELLM_MODEL") or os.getenv("DEFAULT_LLM") or "gpt-3.5-turbo"
|
172
|
+
try:
|
173
|
+
for chunk in Runner.run(agent, instruction):
|
174
|
+
yield chunk
|
175
|
+
except Exception as e:
|
176
|
+
logger.error(f"Error during non-interactive run: {e}", exc_info=True)
|
177
|
+
yield {"messages": [{"role": "assistant", "content": f"An error occurred: {e}"}]}
|
178
|
+
|
151
179
|
if __name__ == "__main__":
|
152
180
|
FamilyTiesBlueprint.main()
|
@@ -1,6 +1,26 @@
|
|
1
1
|
import logging
|
2
|
-
|
2
|
+
logging.basicConfig(level=logging.INFO, format='[%(levelname)s] %(name)s: %(message)s')
|
3
|
+
import os
|
3
4
|
import sys
|
5
|
+
|
6
|
+
# --- Universal Logging Reset ---
|
7
|
+
def force_info_logging():
|
8
|
+
root = logging.getLogger()
|
9
|
+
for handler in root.handlers[:]:
|
10
|
+
root.removeHandler(handler)
|
11
|
+
loglevel = os.environ.get('LOGLEVEL', None)
|
12
|
+
debug_env = os.environ.get('SWARM_DEBUG', '0') == '1'
|
13
|
+
debug_arg = '--debug' in sys.argv
|
14
|
+
if debug_arg or debug_env or (loglevel and loglevel.upper() == 'DEBUG'):
|
15
|
+
level = logging.DEBUG
|
16
|
+
else:
|
17
|
+
level = logging.INFO
|
18
|
+
logging.basicConfig(level=level, format='[%(levelname)s] %(name)s: %(message)s')
|
19
|
+
root.setLevel(level)
|
20
|
+
|
21
|
+
force_info_logging()
|
22
|
+
|
23
|
+
import argparse
|
4
24
|
from typing import List, Dict, Any, Optional, ClassVar
|
5
25
|
|
6
26
|
# Ensure src is in path for BlueprintBase import (if needed, adjust path)
|
@@ -8,6 +28,8 @@ project_root = os.path.abspath(os.path.join(os.path.dirname(__file__), '..', '..
|
|
8
28
|
src_path = os.path.join(project_root, 'src')
|
9
29
|
if src_path not in sys.path: sys.path.insert(0, src_path)
|
10
30
|
|
31
|
+
from typing import Optional
|
32
|
+
from pathlib import Path
|
11
33
|
try:
|
12
34
|
from agents import Agent, Tool, function_tool, Runner
|
13
35
|
from agents.mcp import MCPServer
|
@@ -21,39 +43,66 @@ except ImportError as e:
|
|
21
43
|
print(f"sys.path: {sys.path}")
|
22
44
|
sys.exit(1)
|
23
45
|
|
46
|
+
import argparse
|
47
|
+
|
48
|
+
# --- Logging Setup ---
|
49
|
+
def setup_logging():
|
50
|
+
parser = argparse.ArgumentParser(add_help=False)
|
51
|
+
parser.add_argument('--debug', action='store_true', help='Enable debug logging')
|
52
|
+
args, _ = parser.parse_known_args()
|
53
|
+
loglevel = os.environ.get('LOGLEVEL', None)
|
54
|
+
if args.debug or os.environ.get('SWARM_DEBUG', '0') == '1' or (loglevel and loglevel.upper() == 'DEBUG'):
|
55
|
+
logging.basicConfig(level=logging.DEBUG)
|
56
|
+
else:
|
57
|
+
logging.basicConfig(level=logging.INFO)
|
58
|
+
return args
|
59
|
+
|
60
|
+
args = setup_logging()
|
61
|
+
|
24
62
|
logger = logging.getLogger(__name__)
|
25
63
|
|
26
64
|
# --- Tools ---
|
27
|
-
|
28
|
-
|
29
|
-
"""Generates a basic story outline based on a topic."""
|
30
|
-
logger.info(f"Tool: Generating outline for: {topic}") # Keep INFO for tool exec start
|
31
|
-
# In a real scenario, this might involve more logic or an LLM call.
|
32
|
-
# Adding slight variation for clarity
|
65
|
+
def _create_story_outline(topic: str) -> str:
|
66
|
+
logger.info(f"Tool: Generating outline for: {topic}")
|
33
67
|
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."
|
34
68
|
logger.debug(f"Generated outline: {outline}")
|
35
69
|
return outline
|
36
70
|
|
37
71
|
@function_tool
|
38
|
-
def
|
39
|
-
"""
|
40
|
-
|
41
|
-
|
72
|
+
def create_story_outline(topic: str) -> str:
|
73
|
+
"""Generates a basic story outline based on a topic."""
|
74
|
+
return _create_story_outline(topic)
|
75
|
+
|
76
|
+
def _write_story_part(part_name: str, outline: str, previous_parts: str) -> str:
|
77
|
+
logger.info(f"Tool: Writing story part: {part_name}")
|
42
78
|
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}'"
|
43
79
|
logger.debug(f"Generated content for {part_name}: {content[:100]}...")
|
44
80
|
return content
|
45
81
|
|
46
82
|
@function_tool
|
47
|
-
def
|
48
|
-
"""
|
49
|
-
|
50
|
-
|
83
|
+
def write_story_part(part_name: str, outline: str, previous_parts: str) -> str:
|
84
|
+
"""Writes a specific part of the story using the outline and previous context."""
|
85
|
+
return _write_story_part(part_name, outline, previous_parts)
|
86
|
+
|
87
|
+
def _edit_story(full_story: str, edit_instructions: str) -> str:
|
88
|
+
logger.info(f"Tool: Editing story with instructions: {edit_instructions}")
|
51
89
|
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.]"
|
52
90
|
logger.debug("Editing complete.")
|
53
91
|
return edited_content
|
54
92
|
|
93
|
+
@function_tool
|
94
|
+
def edit_story(full_story: str, edit_instructions: str) -> str:
|
95
|
+
"""Edits the complete story based on instructions."""
|
96
|
+
return _edit_story(full_story, edit_instructions)
|
97
|
+
|
55
98
|
# --- Blueprint Definition ---
|
99
|
+
from rich.console import Console
|
100
|
+
from rich.panel import Panel
|
101
|
+
|
56
102
|
class GaggleBlueprint(BlueprintBase):
|
103
|
+
def __init__(self, blueprint_id: str, config_path: Optional[Path] = None, **kwargs):
|
104
|
+
super().__init__(blueprint_id, config_path=config_path, **kwargs)
|
105
|
+
|
57
106
|
"""A multi-agent blueprint using a Coordinator, Planner, Writer, and Editor for collaborative story writing."""
|
58
107
|
metadata: ClassVar[Dict[str, Any]] = {
|
59
108
|
"name": "GaggleBlueprint",
|
@@ -70,6 +119,23 @@ class GaggleBlueprint(BlueprintBase):
|
|
70
119
|
_openai_client_cache: Dict[str, AsyncOpenAI] = {}
|
71
120
|
_model_instance_cache: Dict[str, Model] = {}
|
72
121
|
|
122
|
+
def display_splash_screen(self, animated: bool = False):
|
123
|
+
console = Console()
|
124
|
+
splash = r'''
|
125
|
+
[bold magenta]
|
126
|
+
____ _ _ ____ _ _
|
127
|
+
/ ___| __ _ _ __ __ _| | ___| |__ / ___|| |_ __ _ _ __| |_ ___
|
128
|
+
| | _ / _` | '_ \ / _` | |/ _ \ '_ \ \___ \| __/ _` | '__| __/ _ \
|
129
|
+
| |_| | (_| | | | | (_| | | __/ | | | ___) | || (_| | | | || __/
|
130
|
+
\____|\__,_|_| |_|\__, |_|\___|_| |_|____/ \__\__,_|_| \__\___|
|
131
|
+
|___/
|
132
|
+
[/bold magenta]
|
133
|
+
[white]Collaborative Story Writing Blueprint[/white]
|
134
|
+
'''
|
135
|
+
panel = Panel(splash, title="[bold magenta]Gaggle Blueprint[/]", border_style="magenta", expand=False)
|
136
|
+
console.print(panel)
|
137
|
+
console.print() # Blank line for spacing
|
138
|
+
|
73
139
|
# --- Model Instantiation Helper --- (Standard helper)
|
74
140
|
def _get_model_instance(self, profile_name: str) -> Model:
|
75
141
|
"""Retrieves or creates an LLM Model instance."""
|
@@ -180,5 +246,41 @@ class GaggleBlueprint(BlueprintBase):
|
|
180
246
|
logger.debug("Gaggle Story Writing Team created. Coordinator is the starting agent.")
|
181
247
|
return coordinator_agent
|
182
248
|
|
249
|
+
async def run(self, messages: List[Dict[str, str]]):
|
250
|
+
"""
|
251
|
+
Run the Gaggle blueprint agentic workflow.
|
252
|
+
Accepts a list of messages (e.g., task prompt from CLI) and yields output chunks.
|
253
|
+
"""
|
254
|
+
# For demonstration, this will run the collaborative story workflow
|
255
|
+
topic = None
|
256
|
+
for msg in messages:
|
257
|
+
if msg.get("role") == "user":
|
258
|
+
topic = msg.get("content")
|
259
|
+
break
|
260
|
+
if not topic:
|
261
|
+
yield {"messages": [{"role": "system", "content": "No topic provided."}]}
|
262
|
+
return
|
263
|
+
# Step 1: Planner creates outline
|
264
|
+
outline = _create_story_outline(topic)
|
265
|
+
yield {"messages": [{"role": "planner", "content": outline}]}
|
266
|
+
# Step 2: Writer writes story parts (simulate parts)
|
267
|
+
story_parts = []
|
268
|
+
for part in ["Beginning", "Middle", "Climax", "End"]:
|
269
|
+
part_text = _write_story_part(part, outline, "\n".join(story_parts))
|
270
|
+
story_parts.append(part_text)
|
271
|
+
yield {"messages": [{"role": "writer", "content": part_text}]}
|
272
|
+
# Step 3: Editor edits the full story
|
273
|
+
full_story = "\n\n".join(story_parts)
|
274
|
+
edited = _edit_story(full_story, "Polish for flow and clarity.")
|
275
|
+
yield {"messages": [{"role": "editor", "content": edited}]}
|
276
|
+
|
277
|
+
async def _run_non_interactive(self, instruction: str, **kwargs):
|
278
|
+
"""Adapter for CLI non-interactive execution, yields results from the public run method. Accepts **kwargs for compatibility."""
|
279
|
+
messages = [{"role": "user", "content": instruction}]
|
280
|
+
async for chunk in self.run(messages, **kwargs):
|
281
|
+
yield chunk
|
282
|
+
|
283
|
+
|
284
|
+
|
183
285
|
if __name__ == "__main__":
|
184
286
|
GaggleBlueprint.main()
|
@@ -116,6 +116,16 @@ def vercel_cli(command: str) -> str:
|
|
116
116
|
|
117
117
|
|
118
118
|
# --- Define the Blueprint ---
|
119
|
+
# === OpenAI GPT-4.1 Prompt Engineering Guide ===
|
120
|
+
# See: https://github.com/openai/openai-cookbook/blob/main/examples/gpt4-1_prompting_guide.ipynb
|
121
|
+
#
|
122
|
+
# Agentic System Prompt Example (recommended for cloud ops agents):
|
123
|
+
SYS_PROMPT_AGENTIC = """
|
124
|
+
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.
|
125
|
+
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.
|
126
|
+
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.
|
127
|
+
"""
|
128
|
+
|
119
129
|
class MonkaiMagicBlueprint(BlueprintBase):
|
120
130
|
"""Blueprint for a cloud operations team inspired by *Monkai Magic*."""
|
121
131
|
metadata: ClassVar[Dict[str, Any]] = {
|
@@ -59,6 +59,13 @@ cypher_instructions = "You are Cypher..."
|
|
59
59
|
tank_instructions = "You are Tank..."
|
60
60
|
|
61
61
|
# --- Blueprint Definition ---
|
62
|
+
from rich.console import Console
|
63
|
+
from rich.panel import Panel
|
64
|
+
from rich.live import Live
|
65
|
+
from rich.text import Text
|
66
|
+
import random
|
67
|
+
import time
|
68
|
+
|
62
69
|
class NebuchaShellzzarBlueprint(BlueprintBase):
|
63
70
|
"""A multi-agent blueprint inspired by The Matrix for sysadmin and coding tasks."""
|
64
71
|
metadata: ClassVar[Dict[str, Any]] = {
|
@@ -68,22 +75,46 @@ class NebuchaShellzzarBlueprint(BlueprintBase):
|
|
68
75
|
"tags": ["matrix", "multi-agent", "shell", "coding", "mcp"],
|
69
76
|
"required_mcp_servers": ["memory"],
|
70
77
|
}
|
71
|
-
_openai_client_cache: Dict[str, AsyncOpenAI] = {}
|
72
78
|
_model_instance_cache: Dict[str, Model] = {}
|
73
79
|
|
74
80
|
# --- ADDED: Splash Screen ---
|
75
|
-
def display_splash_screen(self):
|
76
|
-
|
77
|
-
|
81
|
+
def display_splash_screen(self, animated: bool = False):
|
82
|
+
console = Console()
|
83
|
+
if not animated:
|
84
|
+
splash_text = """
|
78
85
|
[bold green]Wake up, Neo...[/]
|
79
86
|
[green]The Matrix has you...[/]
|
80
87
|
[bold green]Follow the white rabbit.[/]
|
81
88
|
|
82
89
|
Initializing NebulaShellzzar Crew...
|
83
|
-
|
84
|
-
|
85
|
-
|
86
|
-
|
90
|
+
"""
|
91
|
+
panel = Panel(splash_text.strip(), title="[bold green]NebulaShellzzar[/]", border_style="green", expand=False)
|
92
|
+
console.print(panel)
|
93
|
+
console.print() # Add a blank line
|
94
|
+
else:
|
95
|
+
# Animated Matrix rain effect
|
96
|
+
width = 60
|
97
|
+
height = 12
|
98
|
+
charset = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789@#$%&"
|
99
|
+
rain_cols = [0] * width
|
100
|
+
with Live(refresh_per_second=20, console=console, transient=True) as live:
|
101
|
+
for _ in range(30):
|
102
|
+
matrix = ""
|
103
|
+
for y in range(height):
|
104
|
+
line = ""
|
105
|
+
for x in range(width):
|
106
|
+
if random.random() < 0.02:
|
107
|
+
rain_cols[x] = 0
|
108
|
+
char = random.choice(charset) if rain_cols[x] < y else " "
|
109
|
+
line += f"[green]{char}[/]"
|
110
|
+
matrix += line + "\n"
|
111
|
+
panel = Panel(Text.from_markup(matrix), title="[bold green]NebulaShellzzar[/]", border_style="green", expand=False)
|
112
|
+
live.update(panel)
|
113
|
+
time.sleep(0.07)
|
114
|
+
console.print("[bold green]Wake up, Neo...[/]")
|
115
|
+
console.print("[green]The Matrix has you...[/]")
|
116
|
+
console.print("[bold green]Follow the white rabbit.[/]")
|
117
|
+
console.print("\nInitializing NebulaShellzzar Crew...\n")
|
87
118
|
|
88
119
|
def _get_model_instance(self, profile_name: str) -> Model:
|
89
120
|
"""Gets or creates a Model instance for the given profile name."""
|
@@ -100,26 +131,14 @@ Initializing NebulaShellzzar Crew...
|
|
100
131
|
if not model_name:
|
101
132
|
logger.critical(f"LLM profile '{profile_name}' is missing the 'model' key.")
|
102
133
|
raise ValueError(f"Missing 'model' key in LLM profile '{profile_name}'.")
|
103
|
-
|
104
|
-
|
105
|
-
|
106
|
-
|
107
|
-
|
108
|
-
|
109
|
-
|
110
|
-
|
111
|
-
except Exception as e:
|
112
|
-
logger.error(f"Failed to create AsyncOpenAI client for profile '{profile_name}': {e}", exc_info=True)
|
113
|
-
raise ValueError(f"Failed to initialize OpenAI client for profile '{profile_name}': {e}") from e
|
114
|
-
openai_client_instance = self._openai_client_cache[client_cache_key]
|
115
|
-
logger.debug(f"Instantiating OpenAIChatCompletionsModel(model='{model_name}') with specific client instance.")
|
116
|
-
try: model_instance = OpenAIChatCompletionsModel(model=model_name, openai_client=openai_client_instance)
|
117
|
-
except Exception as e:
|
118
|
-
logger.error(f"Failed to instantiate OpenAIChatCompletionsModel for profile '{profile_name}': {e}", exc_info=True)
|
119
|
-
raise ValueError(f"Failed to initialize LLM provider for profile '{profile_name}': {e}") from e
|
120
|
-
else:
|
121
|
-
logger.error(f"Unsupported LLM provider '{provider}' in profile '{profile_name}'.")
|
122
|
-
raise ValueError(f"Unsupported LLM provider: {provider}")
|
134
|
+
|
135
|
+
# Remove redundant client instantiation; rely on framework-level default client
|
136
|
+
# All blueprints now use the default client set at framework init
|
137
|
+
logger.debug(f"Instantiating OpenAIChatCompletionsModel(model='{model_name}') with default client.")
|
138
|
+
try: model_instance = OpenAIChatCompletionsModel(model=model_name)
|
139
|
+
except Exception as e:
|
140
|
+
logger.error(f"Failed to instantiate OpenAIChatCompletionsModel for profile '{profile_name}': {e}", exc_info=True)
|
141
|
+
raise ValueError(f"Failed to initialize LLM provider for profile '{profile_name}': {e}") from e
|
123
142
|
self._model_instance_cache[profile_name] = model_instance
|
124
143
|
return model_instance
|
125
144
|
|
@@ -127,7 +146,6 @@ Initializing NebulaShellzzar Crew...
|
|
127
146
|
"""Creates the Matrix-themed agent team with Morpheus as the coordinator."""
|
128
147
|
logger.debug(f"Creating NebulaShellzzar agent team with {len(mcp_servers)} MCP server(s)...") # Changed to DEBUG
|
129
148
|
self._model_instance_cache = {}
|
130
|
-
self._openai_client_cache = {}
|
131
149
|
default_profile_name = self.config.get("llm_profile", "default")
|
132
150
|
default_model_instance = self._get_model_instance(default_profile_name)
|
133
151
|
logger.debug(f"Using LLM profile '{default_profile_name}' for all agents.") # Changed to DEBUG
|
@@ -216,6 +216,27 @@ class OmniplexBlueprint(BlueprintBase):
|
|
216
216
|
logger.info(f"Omniplex Coordinator created with tools for: {[t.name for t in team_tools]}")
|
217
217
|
return coordinator_agent
|
218
218
|
|
219
|
+
async def run(self, messages: List[Dict[str, Any]], **kwargs) -> Any:
|
220
|
+
"""Main execution entry point for the Omniplex blueprint."""
|
221
|
+
logger.info("OmniplexBlueprint run method called.")
|
222
|
+
instruction = messages[-1].get("content", "") if messages else ""
|
223
|
+
async for chunk in self._run_non_interactive(instruction, **kwargs):
|
224
|
+
yield chunk
|
225
|
+
logger.info("OmniplexBlueprint run method finished.")
|
226
|
+
|
227
|
+
async def _run_non_interactive(self, instruction: str, **kwargs) -> Any:
|
228
|
+
logger.info(f"Running OmniplexBlueprint non-interactively with instruction: '{instruction[:100]}...'")
|
229
|
+
mcp_servers = kwargs.get("mcp_servers", [])
|
230
|
+
agent = self.create_starting_agent(mcp_servers=mcp_servers)
|
231
|
+
from agents import Runner
|
232
|
+
model_name = os.getenv("LITELLM_MODEL") or os.getenv("DEFAULT_LLM") or "gpt-3.5-turbo"
|
233
|
+
try:
|
234
|
+
for chunk in Runner.run(agent, instruction):
|
235
|
+
yield chunk
|
236
|
+
except Exception as e:
|
237
|
+
logger.error(f"Error during non-interactive run: {e}", exc_info=True)
|
238
|
+
yield {"messages": [{"role": "assistant", "content": f"An error occurred: {e}"}]}
|
239
|
+
|
219
240
|
# Standard Python entry point
|
220
241
|
if __name__ == "__main__":
|
221
242
|
OmniplexBlueprint.main()
|
@@ -57,51 +57,41 @@ def execute_shell_command(command: str) -> str:
|
|
57
57
|
|
58
58
|
def read_file(file_path: str) -> str:
|
59
59
|
"""Reads the content of a specified file."""
|
60
|
-
logger.info(f"Reading file: {file_path}")
|
60
|
+
logger.info(f"📄 Reading file: {file_path}")
|
61
61
|
try:
|
62
|
-
# Basic path traversal check (can be enhanced)
|
63
62
|
if ".." in file_path:
|
64
|
-
|
65
|
-
|
66
|
-
# Consider restricting base path if needed
|
67
|
-
# base_path = Path("/workspace").resolve()
|
68
|
-
# target_path = (base_path / file_path).resolve()
|
69
|
-
# if not target_path.is_relative_to(base_path):
|
70
|
-
# return "Error: Access denied."
|
71
|
-
|
63
|
+
logger.warning(f"Attempted path traversal detected in read_file: {file_path}")
|
64
|
+
return "\033[91m❌ Error: Invalid file path (potential traversal).\033[0m"
|
72
65
|
path = Path(file_path)
|
73
66
|
if not path.is_file():
|
74
|
-
|
67
|
+
logger.warning(f"File not found: {file_path}")
|
68
|
+
return f"\033[91m❌ Error: File not found at {file_path}\033[0m"
|
75
69
|
content = path.read_text(encoding='utf-8')
|
76
70
|
logger.info(f"Successfully read {len(content)} characters from {file_path}")
|
77
|
-
# Truncate long files?
|
78
71
|
max_len = 10000
|
79
72
|
if len(content) > max_len:
|
80
|
-
|
81
|
-
|
82
|
-
return content
|
73
|
+
logger.warning(f"File {file_path} truncated to {max_len} characters.")
|
74
|
+
return f"\033[93m⚠️ {content[:max_len]}\n... [File Truncated]\033[0m"
|
75
|
+
return f"\033[92m✅ File read successfully!\033[0m\n\033[94m{content}\033[0m"
|
83
76
|
except Exception as e:
|
84
77
|
logger.error(f"Error reading file '{file_path}': {e}", exc_info=True)
|
85
|
-
return f"Error reading file: {e}"
|
78
|
+
return f"\033[91m❌ Error reading file: {e}\033[0m"
|
86
79
|
|
87
80
|
def write_file(file_path: str, content: str) -> str:
|
88
81
|
"""Writes content to a specified file, creating directories if needed."""
|
89
|
-
logger.info(f"Writing to file: {file_path}")
|
82
|
+
logger.info(f"✏️ Writing to file: {file_path}")
|
90
83
|
try:
|
91
|
-
# Basic path traversal check
|
92
84
|
if ".." in file_path:
|
93
|
-
|
94
|
-
|
95
|
-
# Consider restricting base path
|
96
|
-
|
85
|
+
logger.warning(f"Attempted path traversal detected in write_file: {file_path}")
|
86
|
+
return "\033[91m❌ Error: Invalid file path (potential traversal).\033[0m"
|
97
87
|
path = Path(file_path)
|
98
88
|
path.parent.mkdir(parents=True, exist_ok=True)
|
99
89
|
path.write_text(content, encoding='utf-8')
|
100
90
|
logger.info(f"Successfully wrote {len(content)} characters to {file_path}")
|
101
|
-
return f"Successfully wrote to {file_path}"
|
91
|
+
return f"\033[92m✅ Successfully wrote to {file_path}\033[0m"
|
102
92
|
except Exception as e:
|
103
93
|
logger.error(f"Error writing file '{file_path}': {e}", exc_info=True)
|
104
|
-
return f"Error writing file: {e}"
|
94
|
+
return f"\033[91m❌ Error writing file: {e}\033[0m"
|
105
95
|
|
106
96
|
def list_files(directory_path: str = ".") -> str:
|
107
97
|
"""Lists files and directories in a specified path."""
|
@@ -130,6 +120,16 @@ def list_files(directory_path: str = ".") -> str:
|
|
130
120
|
|
131
121
|
# --- RueCodeBlueprint Definition ---
|
132
122
|
|
123
|
+
# === OpenAI GPT-4.1 Prompt Engineering Guide ===
|
124
|
+
# See: https://github.com/openai/openai-cookbook/blob/main/examples/gpt4-1_prompting_guide.ipynb
|
125
|
+
#
|
126
|
+
# Agentic System Prompt Example (recommended for code generation/repair agents):
|
127
|
+
SYS_PROMPT_AGENTIC = """
|
128
|
+
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.
|
129
|
+
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.
|
130
|
+
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.
|
131
|
+
"""
|
132
|
+
|
133
133
|
class RueCodeBlueprint(BlueprintBase):
|
134
134
|
"""
|
135
135
|
A blueprint designed for code generation, execution, and file system interaction.
|
@@ -288,4 +288,3 @@ class RueCodeBlueprint(BlueprintBase):
|
|
288
288
|
yield {"messages": [{"role": "assistant", "content": f"An error occurred: {e}"}]}
|
289
289
|
|
290
290
|
logger.info("RueCodeBlueprint run finished.")
|
291
|
-
|
@@ -27,6 +27,16 @@ class SuggestionsOutput(TypedDict):
|
|
27
27
|
suggestions: List[str]
|
28
28
|
|
29
29
|
# --- Define the Blueprint ---
|
30
|
+
# === OpenAI GPT-4.1 Prompt Engineering Guide ===
|
31
|
+
# See: https://github.com/openai/openai-cookbook/blob/main/examples/gpt4-1_prompting_guide.ipynb
|
32
|
+
#
|
33
|
+
# Agentic System Prompt Example (recommended for structured output/suggestion agents):
|
34
|
+
SYS_PROMPT_AGENTIC = """
|
35
|
+
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.
|
36
|
+
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.
|
37
|
+
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.
|
38
|
+
"""
|
39
|
+
|
30
40
|
class SuggestionBlueprint(BlueprintBase):
|
31
41
|
"""A blueprint defining an agent that generates structured JSON suggestions using output_type."""
|
32
42
|
|
@@ -42,7 +52,6 @@ class SuggestionBlueprint(BlueprintBase):
|
|
42
52
|
}
|
43
53
|
|
44
54
|
# Caches
|
45
|
-
_openai_client_cache: Dict[str, AsyncOpenAI] = {}
|
46
55
|
_model_instance_cache: Dict[str, Model] = {}
|
47
56
|
|
48
57
|
# --- Model Instantiation Helper --- (Standard helper)
|
@@ -61,19 +70,12 @@ class SuggestionBlueprint(BlueprintBase):
|
|
61
70
|
if not model_name: raise ValueError(f"Missing 'model' in profile '{profile_name}'.")
|
62
71
|
if provider != "openai": raise ValueError(f"Unsupported provider: {provider}")
|
63
72
|
|
64
|
-
|
65
|
-
|
66
|
-
client_kwargs = { "api_key": profile_data.get("api_key"), "base_url": profile_data.get("base_url") }
|
67
|
-
filtered_kwargs = {k: v for k, v in client_kwargs.items() if v is not None}
|
68
|
-
log_kwargs = {k:v for k,v in filtered_kwargs.items() if k != 'api_key'}
|
69
|
-
logger.debug(f"Creating new AsyncOpenAI client for '{profile_name}': {log_kwargs}")
|
70
|
-
try: self._openai_client_cache[client_cache_key] = AsyncOpenAI(**filtered_kwargs)
|
71
|
-
except Exception as e: raise ValueError(f"Failed to init client: {e}") from e
|
72
|
-
client = self._openai_client_cache[client_cache_key]
|
73
|
+
# Remove redundant client instantiation; rely on framework-level default client
|
74
|
+
# All blueprints now use the default client set at framework init
|
73
75
|
logger.debug(f"Instantiating OpenAIChatCompletionsModel(model='{model_name}') for '{profile_name}'.")
|
74
76
|
try:
|
75
77
|
# Ensure the model selected supports structured output (most recent OpenAI do)
|
76
|
-
model_instance = OpenAIChatCompletionsModel(model=model_name
|
78
|
+
model_instance = OpenAIChatCompletionsModel(model=model_name)
|
77
79
|
self._model_instance_cache[profile_name] = model_instance
|
78
80
|
return model_instance
|
79
81
|
except Exception as e: raise ValueError(f"Failed to init LLM: {e}") from e
|
@@ -82,7 +84,6 @@ class SuggestionBlueprint(BlueprintBase):
|
|
82
84
|
"""Create the SuggestionAgent."""
|
83
85
|
logger.debug("Creating SuggestionAgent...")
|
84
86
|
self._model_instance_cache = {}
|
85
|
-
self._openai_client_cache = {}
|
86
87
|
|
87
88
|
default_profile_name = self.config.get("llm_profile", "default")
|
88
89
|
# Verify the chosen profile/model supports structured output if possible, or rely on OpenAI's newer models
|
@@ -106,5 +107,27 @@ class SuggestionBlueprint(BlueprintBase):
|
|
106
107
|
logger.debug("SuggestionAgent created with output_type enforcement.")
|
107
108
|
return suggestion_agent
|
108
109
|
|
110
|
+
async def run(self, messages: List[Dict[str, Any]], **kwargs) -> Any:
|
111
|
+
"""Main execution entry point for the Suggestion blueprint."""
|
112
|
+
logger.info("SuggestionBlueprint run method called.")
|
113
|
+
instruction = messages[-1].get("content", "") if messages else ""
|
114
|
+
async for chunk in self._run_non_interactive(instruction, **kwargs):
|
115
|
+
yield chunk
|
116
|
+
logger.info("SuggestionBlueprint run method finished.")
|
117
|
+
|
118
|
+
async def _run_non_interactive(self, instruction: str, **kwargs) -> Any:
|
119
|
+
logger.info(f"Running SuggestionBlueprint non-interactively with instruction: '{instruction[:100]}...'")
|
120
|
+
mcp_servers = kwargs.get("mcp_servers", [])
|
121
|
+
agent = self.create_starting_agent(mcp_servers=mcp_servers)
|
122
|
+
from agents import Runner
|
123
|
+
import os
|
124
|
+
model_name = os.getenv("LITELLM_MODEL") or os.getenv("DEFAULT_LLM") or "gpt-3.5-turbo"
|
125
|
+
try:
|
126
|
+
for chunk in Runner.run(agent, instruction):
|
127
|
+
yield chunk
|
128
|
+
except Exception as e:
|
129
|
+
logger.error(f"Error during non-interactive run: {e}", exc_info=True)
|
130
|
+
yield {"messages": [{"role": "assistant", "content": f"An error occurred: {e}"}]}
|
131
|
+
|
109
132
|
if __name__ == "__main__":
|
110
133
|
SuggestionBlueprint.main()
|
File without changes
|
{open_swarm-0.1.1744936173.dist-info → open_swarm-0.1.1744936234.dist-info}/entry_points.txt
RENAMED
File without changes
|
{open_swarm-0.1.1744936173.dist-info → open_swarm-0.1.1744936234.dist-info}/licenses/LICENSE
RENAMED
File without changes
|