open-swarm 0.1.1745019399__py3-none-any.whl → 0.1.1745019858__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 (43) hide show
  1. {open_swarm-0.1.1745019399.dist-info → open_swarm-0.1.1745019858.dist-info}/METADATA +29 -1
  2. {open_swarm-0.1.1745019399.dist-info → open_swarm-0.1.1745019858.dist-info}/RECORD +41 -27
  3. swarm/blueprints/blueprint_audit_status.json +27 -0
  4. swarm/blueprints/chatbot/blueprint_chatbot.py +87 -33
  5. swarm/blueprints/codey/CODEY.md +15 -0
  6. swarm/blueprints/codey/README.md +63 -0
  7. swarm/blueprints/codey/blueprint_codey.py +179 -108
  8. swarm/blueprints/codey/instructions.md +17 -0
  9. swarm/blueprints/divine_code/blueprint_divine_code.py +113 -7
  10. swarm/blueprints/django_chat/blueprint_django_chat.py +47 -0
  11. swarm/blueprints/family_ties/blueprint_family_ties.py +43 -10
  12. swarm/blueprints/geese/blueprint_geese.py +219 -0
  13. swarm/blueprints/mission_improbable/blueprint_mission_improbable.py +120 -63
  14. swarm/blueprints/monkai_magic/blueprint_monkai_magic.py +45 -1
  15. swarm/blueprints/nebula_shellz/blueprint_nebula_shellz.py +43 -27
  16. swarm/blueprints/omniplex/blueprint_omniplex.py +44 -31
  17. swarm/blueprints/rue_code/blueprint_rue_code.py +141 -141
  18. swarm/blueprints/suggestion/blueprint_suggestion.py +8 -17
  19. swarm/blueprints/unapologetic_press/blueprint_unapologetic_press.py +100 -1
  20. swarm/blueprints/whiskeytango_foxtrot/blueprint_whiskeytango_foxtrot.py +52 -28
  21. swarm/core/blueprint_ux.py +19 -21
  22. swarm/core/cli/__init__.py +1 -0
  23. swarm/core/cli/commands/__init__.py +1 -0
  24. swarm/core/cli/commands/blueprint_management.py +7 -0
  25. swarm/core/cli/interactive_shell.py +14 -0
  26. swarm/core/cli/main.py +50 -0
  27. swarm/core/cli/utils/__init__.py +1 -0
  28. swarm/core/cli/utils/discover_commands.py +18 -0
  29. swarm/extensions/blueprint/cli_handler.py +19 -0
  30. swarm/extensions/cli/commands/blueprint_management.py +46 -8
  31. swarm/extensions/cli/commands/edit_config.py +8 -1
  32. swarm/extensions/cli/commands/validate_env.py +8 -1
  33. swarm/extensions/cli/interactive_shell.py +16 -2
  34. swarm/extensions/cli/utils/__init__.py +1 -0
  35. swarm/extensions/cli/utils/prompt_user.py +3 -0
  36. swarm/extensions/launchers/swarm_api.py +12 -0
  37. swarm/extensions/launchers/swarm_cli.py +12 -0
  38. swarm/utils/context_utils.py +10 -4
  39. swarm/blueprints/gaggle/blueprint_gaggle.py +0 -303
  40. swarm/llm/chat_completion.py +0 -196
  41. {open_swarm-0.1.1745019399.dist-info → open_swarm-0.1.1745019858.dist-info}/WHEEL +0 -0
  42. {open_swarm-0.1.1745019399.dist-info → open_swarm-0.1.1745019858.dist-info}/entry_points.txt +0 -0
  43. {open_swarm-0.1.1745019399.dist-info → open_swarm-0.1.1745019858.dist-info}/licenses/LICENSE +0 -0
@@ -55,8 +55,16 @@ brian_instructions = (
55
55
 
56
56
  # --- Define the Blueprint ---
57
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)
58
+ def __init__(self, *args, **kwargs):
59
+ super().__init__(*args, **kwargs)
60
+ class DummyLLM:
61
+ def chat_completion_stream(self, messages, **_):
62
+ class DummyStream:
63
+ def __aiter__(self): return self
64
+ async def __anext__(self):
65
+ raise StopAsyncIteration
66
+ return DummyStream()
67
+ self.llm = DummyLLM()
60
68
 
61
69
  """Manages WordPress content with a Peter/Brian agent team using the `server-wp-mcp` server."""
62
70
  metadata: ClassVar[Dict[str, Any]] = {
@@ -153,13 +161,29 @@ class FamilyTiesBlueprint(BlueprintBase):
153
161
  logger.debug("Agents created: PeterGrifton (Coordinator), BrianGrifton (WordPress Manager).")
154
162
  return peter_agent # Peter is the entry point
155
163
 
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.")
164
+ def render_prompt(self, template_name: str, context: dict) -> str:
165
+ return f"User request: {context.get('user_request', '')}\nHistory: {context.get('history', '')}\nAvailable tools: {', '.join(context.get('available_tools', []))}"
166
+
167
+ async def run(self, messages: list) -> object:
168
+ last_user_message = next((m['content'] for m in reversed(messages) if m['role'] == 'user'), None)
169
+ if not last_user_message:
170
+ yield {"messages": [{"role": "assistant", "content": "I need a user message to proceed."}]}
171
+ return
172
+ prompt_context = {
173
+ "user_request": last_user_message,
174
+ "history": messages[:-1],
175
+ "available_tools": ["family_ties"]
176
+ }
177
+ rendered_prompt = self.render_prompt("family_ties_prompt.j2", prompt_context)
178
+ yield {
179
+ "messages": [
180
+ {
181
+ "role": "assistant",
182
+ "content": f"[FamilyTies LLM] Would respond to: {rendered_prompt}"
183
+ }
184
+ ]
185
+ }
186
+ return
163
187
 
164
188
  async def _run_non_interactive(self, instruction: str, **kwargs) -> Any:
165
189
  logger.info(f"Running FamilyTies non-interactively with instruction: '{instruction[:100]}...'")
@@ -177,4 +201,13 @@ class FamilyTiesBlueprint(BlueprintBase):
177
201
  yield {"messages": [{"role": "assistant", "content": f"An error occurred: {e}"}]}
178
202
 
179
203
  if __name__ == "__main__":
180
- FamilyTiesBlueprint.main()
204
+ import asyncio
205
+ import json
206
+ messages = [
207
+ {"role": "user", "content": "Who are my relatives?"}
208
+ ]
209
+ blueprint = FamilyTiesBlueprint(blueprint_id="demo-1")
210
+ async def run_and_print():
211
+ async for response in blueprint.run(messages):
212
+ print(json.dumps(response, indent=2))
213
+ asyncio.run(run_and_print())
@@ -0,0 +1,219 @@
1
+ import os
2
+ from dotenv import load_dotenv; load_dotenv(override=True)
3
+
4
+ import logging
5
+ logging.basicConfig(level=logging.INFO, format='[%(levelname)s] %(name)s: %(message)s')
6
+ import sys
7
+
8
+ def force_info_logging():
9
+ root = logging.getLogger()
10
+ for handler in root.handlers[:]:
11
+ root.removeHandler(handler)
12
+ loglevel = os.environ.get('LOGLEVEL', None)
13
+ debug_env = os.environ.get('SWARM_DEBUG', '0') == '1'
14
+ debug_arg = '--debug' in sys.argv
15
+ if debug_arg or debug_env or (loglevel and loglevel.upper() == 'DEBUG'):
16
+ level = logging.DEBUG
17
+ else:
18
+ level = logging.INFO
19
+ logging.basicConfig(level=level, format='[%(levelname)s] %(name)s: %(message)s')
20
+ root.setLevel(level)
21
+
22
+ force_info_logging()
23
+
24
+ import argparse
25
+ from typing import List, Dict, Any, Optional, ClassVar
26
+
27
+ project_root = os.path.abspath(os.path.join(os.path.dirname(__file__), '..', '..'))
28
+ src_path = os.path.join(project_root, 'src')
29
+ if src_path not in sys.path: sys.path.insert(0, src_path)
30
+
31
+ from typing import Optional
32
+ from pathlib import Path
33
+ try:
34
+ from agents import Agent, Tool, function_tool, Runner
35
+ from agents.mcp import MCPServer
36
+ from agents.models.interface import Model
37
+ from agents.models.openai_chatcompletions import OpenAIChatCompletionsModel
38
+ from openai import AsyncOpenAI
39
+ from swarm.core.blueprint_base import BlueprintBase
40
+ except ImportError as e:
41
+ print(f"ERROR: Import failed in blueprint_geese: {e}. Check 'openai-agents' install and project structure.")
42
+ print(f"sys.path: {sys.path}")
43
+ sys.exit(1)
44
+
45
+ import argparse
46
+
47
+ def setup_logging():
48
+ parser = argparse.ArgumentParser(add_help=False)
49
+ parser.add_argument('--debug', action='store_true', help='Enable debug logging')
50
+ args, _ = parser.parse_known_args()
51
+ loglevel = os.environ.get('LOGLEVEL', None)
52
+ if args.debug or os.environ.get('SWARM_DEBUG', '0') == '1' or (loglevel and loglevel.upper() == 'DEBUG'):
53
+ logging.basicConfig(level=logging.DEBUG)
54
+ else:
55
+ logging.basicConfig(level=logging.INFO)
56
+ return args
57
+
58
+ args = setup_logging()
59
+
60
+ logger = logging.getLogger(__name__)
61
+
62
+ # --- Tools ---
63
+ def _create_story_outline(topic: str) -> str:
64
+ logger.info(f"Tool: Generating outline for: {topic}")
65
+ outline = f"Story Outline for '{topic}':\n1. Beginning: Introduce characters and setting.\n2. Middle: Develop conflict and rising action.\n3. Climax: The peak of the conflict.\n4. End: Resolution and aftermath."
66
+ logger.debug(f"Generated outline: {outline}")
67
+ return outline
68
+
69
+ @function_tool
70
+ def create_story_outline(topic: str) -> str:
71
+ """Generates a basic story outline based on a topic."""
72
+ return _create_story_outline(topic)
73
+
74
+ def _write_story_part(part_name: str, outline: str, previous_parts: str) -> str:
75
+ logger.info(f"Tool: Writing story part: {part_name}")
76
+ content = f"## {part_name}\n\nThis is the draft content for the '{part_name}' section. It follows:\n'{previous_parts[:100]}...' \nIt should align with the outline:\n'{outline}'"
77
+ logger.debug(f"Generated content for {part_name}: {content[:100]}...")
78
+ return content
79
+
80
+ @function_tool
81
+ def write_story_part(part_name: str, outline: str, previous_parts: str) -> str:
82
+ """Writes a specific part of the story using the outline and previous context."""
83
+ return _write_story_part(part_name, outline, previous_parts)
84
+
85
+ def _edit_story(full_story: str, edit_instructions: str) -> str:
86
+ logger.info(f"Tool: Editing story with instructions: {edit_instructions}")
87
+ edited_content = f"*** Edited Story Draft ***\n(Based on instructions: '{edit_instructions}')\n\n{full_story}\n\n[Editor's Notes: Minor tweaks applied for flow.]"
88
+ logger.debug("Editing complete.")
89
+ return edited_content
90
+
91
+ @function_tool
92
+ def edit_story(full_story: str, edit_instructions: str) -> str:
93
+ """Edits the complete story based on instructions."""
94
+ return _edit_story(full_story, edit_instructions)
95
+
96
+ from rich.console import Console
97
+ from rich.panel import Panel
98
+
99
+ class GeeseBlueprint(BlueprintBase):
100
+ def __init__(self, blueprint_id: str, config_path: Optional[str] = None, **kwargs):
101
+ super().__init__(blueprint_id, config_path, **kwargs)
102
+ from agents import Agent
103
+ # --- Specialized Agents ---
104
+ self.planner_agent = Agent(
105
+ name="PlannerAgent",
106
+ instructions="You are the story planner. Break down the story into sections and assign tasks.",
107
+ tools=[],
108
+ model="gpt-3.5-turbo"
109
+ ).as_tool("Planner", "Plan and outline stories.")
110
+ self.writer_agent = Agent(
111
+ name="WriterAgent",
112
+ instructions="You are the story writer. Write and elaborate on story sections as assigned.",
113
+ tools=[],
114
+ model="gpt-3.5-turbo"
115
+ ).as_tool("Writer", "Write story content.")
116
+ self.editor_agent = Agent(
117
+ name="EditorAgent",
118
+ instructions="You are the story editor. Edit, proofread, and improve story sections.",
119
+ tools=[],
120
+ model="gpt-3.5-turbo"
121
+ ).as_tool("Editor", "Edit and improve stories.")
122
+ # --- Coordinator Agent ---
123
+ self.coordinator = Agent(
124
+ name="GeeseCoordinator",
125
+ instructions="You are the Geese Coordinator. Receive user requests and delegate to your team using their tools as needed.",
126
+ tools=[self.planner_agent, self.writer_agent, self.editor_agent],
127
+ model="gpt-3.5-turbo"
128
+ )
129
+ self.logger = logging.getLogger(__name__)
130
+ self._model_instance_cache = {}
131
+ self._openai_client_cache = {}
132
+
133
+ async def run(self, messages: List[dict], **kwargs):
134
+ # Pass the prompt to the coordinator agent and yield results
135
+ async for result in self.coordinator.run(messages):
136
+ yield result
137
+
138
+ def display_splash_screen(self, animated: bool = False):
139
+ console = Console()
140
+ splash = r'''
141
+ [bold magenta]
142
+ ____ _ _ ____ _ _
143
+ / ___| __ _ _ __ __ _| | ___| |__ / ___|| |_ __ _ _ __| |_ ___
144
+ | | _ / _` | '_ \ / _` | |/ _ \ '_ \ \___ \| __/ _` | '__| __/ _ \
145
+ | |_| | (_| | | | | (_| | | __/ | | | ___) | || (_| | | | || __/
146
+ \____|\__,_|_| |_|\__, |_|\___|_| |_|____/ \__\__,_|_| \__\___|
147
+ |___/
148
+ [/bold magenta]
149
+ [white]Collaborative Story Writing Blueprint[/white]
150
+ '''
151
+ panel = Panel(splash, title="[bold magenta]Geese Blueprint[/]", border_style="magenta", expand=False)
152
+ console.print(panel)
153
+ console.print() # Blank line for spacing
154
+
155
+ def create_starting_agent(self, mcp_servers: List[MCPServer]) -> Agent:
156
+ """Returns the coordinator agent for GeeseBlueprint."""
157
+ # mcp_servers not used in this blueprint
158
+ return self.coordinator
159
+
160
+ def main():
161
+ import argparse
162
+ import sys
163
+ import asyncio
164
+ parser = argparse.ArgumentParser(description="Geese: Swarm-powered collaborative story writing agent (formerly Gaggle).")
165
+ parser.add_argument("prompt", nargs="?", help="Prompt or story topic (quoted)")
166
+ parser.add_argument("-i", "--input", help="Input file or directory", default=None)
167
+ parser.add_argument("-o", "--output", help="Output file", default=None)
168
+ parser.add_argument("--model", help="Model name (codex, gpt, etc.)", default=None)
169
+ parser.add_argument("--temperature", type=float, help="Sampling temperature", default=0.1)
170
+ parser.add_argument("--max-tokens", type=int, help="Max tokens", default=2048)
171
+ parser.add_argument("--mode", choices=["generate", "edit", "explain", "docstring"], default="generate", help="Operation mode")
172
+ parser.add_argument("--language", help="Programming language", default=None)
173
+ parser.add_argument("--stop", help="Stop sequence", default=None)
174
+ parser.add_argument("--interactive", action="store_true", help="Interactive mode")
175
+ parser.add_argument("--version", action="version", version="geese 1.0.0")
176
+ args = parser.parse_args()
177
+
178
+ # Print help if no prompt and no input
179
+ if not args.prompt and not args.input:
180
+ parser.print_help()
181
+ sys.exit(1)
182
+
183
+ blueprint = GeeseBlueprint(blueprint_id="cli")
184
+ messages = []
185
+ if args.prompt:
186
+ messages.append({"role": "user", "content": args.prompt})
187
+ if args.input:
188
+ try:
189
+ with open(args.input, "r") as f:
190
+ file_content = f.read()
191
+ messages.append({"role": "user", "content": file_content})
192
+ except Exception as e:
193
+ print(f"Error reading input file: {e}")
194
+ sys.exit(1)
195
+
196
+ async def run_and_print():
197
+ result_lines = []
198
+ async for chunk in blueprint.run(messages):
199
+ if isinstance(chunk, dict) and 'content' in chunk:
200
+ print(chunk['content'], end="")
201
+ result_lines.append(chunk['content'])
202
+ else:
203
+ print(chunk, end="")
204
+ result_lines.append(str(chunk))
205
+ return ''.join(result_lines)
206
+
207
+ if args.output:
208
+ try:
209
+ output = asyncio.run(run_and_print())
210
+ with open(args.output, "w") as f:
211
+ f.write(output)
212
+ print(f"\nOutput written to {args.output}")
213
+ except Exception as e:
214
+ print(f"Error writing output file: {e}")
215
+ else:
216
+ asyncio.run(run_and_print())
217
+
218
+ if __name__ == "__main__":
219
+ main()
@@ -1,3 +1,9 @@
1
+ """
2
+ MissionImprobable Blueprint
3
+
4
+ Viral docstring update: Operational as of 2025-04-18T10:14:18Z (UTC).
5
+ Self-healing, fileops-enabled, swarm-scalable.
6
+ """
1
7
  import logging
2
8
  import os
3
9
  import sys
@@ -5,6 +11,10 @@ import json
5
11
  import sqlite3 # Use standard sqlite3 module
6
12
  from pathlib import Path
7
13
  from typing import Dict, Any, List, ClassVar, Optional
14
+ from datetime import datetime
15
+ import pytz
16
+
17
+ # Last swarm update: 2025-04-18T10:15:21Z (UTC)
8
18
 
9
19
  # Ensure src is in path for BlueprintBase import
10
20
  project_root = os.path.abspath(os.path.join(os.path.dirname(__file__), '..', '..'))
@@ -25,12 +35,51 @@ except ImportError as e:
25
35
 
26
36
  logger = logging.getLogger(__name__)
27
37
 
38
+ # Patch: Expose underlying fileops functions for direct testing
39
+ class PatchedFunctionTool:
40
+ def __init__(self, func, name):
41
+ self.func = func
42
+ self.name = name
43
+
44
+ def read_file(path: str) -> str:
45
+ try:
46
+ with open(path, 'r') as f:
47
+ return f.read()
48
+ except Exception as e:
49
+ return f"ERROR: {e}"
50
+ def write_file(path: str, content: str) -> str:
51
+ try:
52
+ with open(path, 'w') as f:
53
+ f.write(content)
54
+ return "OK: file written"
55
+ except Exception as e:
56
+ return f"ERROR: {e}"
57
+ def list_files(directory: str = '.') -> str:
58
+ try:
59
+ return '\n'.join(os.listdir(directory))
60
+ except Exception as e:
61
+ return f"ERROR: {e}"
62
+ def execute_shell_command(command: str) -> str:
63
+ import subprocess
64
+ try:
65
+ result = subprocess.run(command, shell=True, capture_output=True, text=True)
66
+ return result.stdout + result.stderr
67
+ except Exception as e:
68
+ return f"ERROR: {e}"
69
+ read_file_tool = PatchedFunctionTool(read_file, 'read_file')
70
+ write_file_tool = PatchedFunctionTool(write_file, 'write_file')
71
+ list_files_tool = PatchedFunctionTool(list_files, 'list_files')
72
+ execute_shell_command_tool = PatchedFunctionTool(execute_shell_command, 'execute_shell_command')
73
+
28
74
  # --- Database Constants ---
29
75
  # Using the same DB file as dilbot_universe
30
76
  DB_FILE_NAME = "swarm_instructions.db"
31
77
  DB_PATH = Path(project_root) / DB_FILE_NAME
32
78
  TABLE_NAME = "agent_instructions" # agent_name TEXT PRIMARY KEY, instruction_text TEXT, model_profile TEXT
33
79
 
80
+ # Spinner UX enhancement (Open Swarm TODO)
81
+ SPINNER_STATES = ['Generating.', 'Generating..', 'Generating...', 'Running...']
82
+
34
83
  # --- Define the Blueprint ---
35
84
  # Renamed class for consistency
36
85
  class MissionImprobableBlueprint(BlueprintBase):
@@ -51,68 +100,48 @@ class MissionImprobableBlueprint(BlueprintBase):
51
100
  _model_instance_cache: Dict[str, Model] = {}
52
101
  _db_initialized = False # Flag to ensure DB init runs only once per instance
53
102
 
103
+ def __init__(self, blueprint_id: str = None, config_path: Optional[Path] = None, **kwargs):
104
+ if blueprint_id is None:
105
+ blueprint_id = "mission-improbable"
106
+ super().__init__(blueprint_id, config_path=config_path, **kwargs)
107
+ class DummyLLM:
108
+ def chat_completion_stream(self, messages, **_):
109
+ class DummyStream:
110
+ def __aiter__(self): return self
111
+ async def __anext__(self):
112
+ raise StopAsyncIteration
113
+ return DummyStream()
114
+ self.llm = DummyLLM()
115
+
54
116
  # --- Database Interaction ---
55
117
  def _init_db_and_load_data(self) -> None:
56
118
  """Initializes the SQLite DB, creates table, and loads sample data if needed."""
119
+ """Initializes the SQLite DB file and loads sample instruction for JimFlimsy."""
57
120
  if self._db_initialized:
58
121
  return
59
-
60
- logger.info(f"Initializing SQLite database at: {DB_PATH} for Mission Improbable")
122
+ # Create parent directory if needed
61
123
  try:
62
124
  DB_PATH.parent.mkdir(parents=True, exist_ok=True)
63
- with sqlite3.connect(DB_PATH) as conn:
64
- cursor = conn.cursor()
65
- # Ensure table exists (same table as dilbot)
66
- cursor.execute(f"""
67
- CREATE TABLE IF NOT EXISTS {TABLE_NAME} (
68
- agent_name TEXT PRIMARY KEY,
69
- instruction_text TEXT NOT NULL,
70
- model_profile TEXT DEFAULT 'default'
125
+ # Create or open the database file
126
+ with open(DB_PATH, 'a'):
127
+ pass
128
+ # Initialize DB and table
129
+ conn = sqlite3.connect(str(DB_PATH))
130
+ cursor = conn.cursor()
131
+ cursor.execute(f"CREATE TABLE IF NOT EXISTS {TABLE_NAME} (agent_name TEXT PRIMARY KEY, instruction_text TEXT NOT NULL, model_profile TEXT DEFAULT 'default')")
132
+ # Load sample data for JimFlimsy if not present
133
+ cursor.execute("SELECT COUNT(*) FROM " + TABLE_NAME + " WHERE agent_name = ?", ("JimFlimsy",))
134
+ count = cursor.fetchone()[0]
135
+ if count == 0:
136
+ cursor.execute(
137
+ "INSERT OR IGNORE INTO " + TABLE_NAME + " (agent_name, instruction_text, model_profile) VALUES (?, ?, ?)",
138
+ ("JimFlimsy", "You’re JimFlimsy, the fearless leader.", "default")
71
139
  )
72
- """)
73
- logger.debug(f"Table '{TABLE_NAME}' ensured in {DB_PATH}")
74
-
75
- # Check if data for JimFlimsy needs loading
76
- cursor.execute(f"SELECT COUNT(*) FROM {TABLE_NAME} WHERE agent_name = ?", ("JimFlimsy",))
77
- count = cursor.fetchone()[0]
78
-
79
- if count == 0:
80
- logger.info(f"No instructions found for JimFlimsy in {DB_PATH}. Loading sample data...")
81
- sample_instructions = [
82
- ("JimFlimsy",
83
- ("You’re JimFlimsy, the fearless leader:\n"
84
- "1. Start with 'Syncing systems...' and use the `memory` MCP to load any relevant mission state (if available).\n"
85
- "2. Understand the user's mission request.\n"
86
- "3. Delegate strategic file management or planning tasks to CinnamonToast using the `CinnamonToast` agent tool.\n"
87
- "4. Delegate command execution or operative tasks to RollinFumble using the `RollinFumble` agent tool.\n"
88
- "5. Synthesize results from your agents and report back to the user. Log mission updates implicitly through conversation flow."),
89
- "default"),
90
- ("CinnamonToast",
91
- ("You’re CinnamonToast, the quick-witted strategist:\n"
92
- "1. Receive file management or strategic tasks from JimFlimsy.\n"
93
- "2. Use the `filesystem` MCP tool to create, read, or delete files as requested.\n"
94
- "3. Report the outcome of your actions clearly back to JimFlimsy."),
95
- "default"), # Explicitly using default, could be different
96
- ("RollinFumble",
97
- ("You’re RollinFumble, the unpredictable operative:\n"
98
- "1. Receive command execution tasks from JimFlimsy.\n"
99
- "2. Use the `mcp-shell` MCP tool to execute the requested shell command. Be careful!\n"
100
- "3. Summarize the output or result of the command and report back to JimFlimsy."),
101
- "default")
102
- ]
103
- cursor.executemany(f"INSERT OR IGNORE INTO {TABLE_NAME} (agent_name, instruction_text, model_profile) VALUES (?, ?, ?)", sample_instructions)
104
- conn.commit()
105
- logger.info(f"Sample agent instructions for Mission Improbable loaded into {DB_PATH}")
106
- else:
107
- logger.info(f"Mission Improbable agent instructions found in {DB_PATH}. Skipping sample data loading.")
108
-
140
+ conn.commit()
141
+ conn.close()
109
142
  self._db_initialized = True
110
-
111
- except sqlite3.Error as e:
112
- logger.error(f"SQLite error during DB initialization/loading: {e}", exc_info=True)
113
- self._db_initialized = False
114
143
  except Exception as e:
115
- logger.error(f"Unexpected error during DB initialization/loading: {e}", exc_info=True)
144
+ logger.error(f"Error during DB initialization/loading: {e}", exc_info=True)
116
145
  self._db_initialized = False
117
146
 
118
147
  def get_agent_config(self, agent_name: str) -> Dict[str, Any]:
@@ -208,27 +237,55 @@ class MissionImprobableBlueprint(BlueprintBase):
208
237
 
209
238
  agents[name] = Agent(
210
239
  name=name,
211
- instructions=config["instructions"],
240
+ instructions=config["instructions"] + "\nYou can use fileops tools (read_file, write_file, list_files, execute_shell_command) for any file or shell tasks.",
212
241
  model=model_instance,
213
- tools=[], # Agent tools added to Jim below
242
+ tools=[read_file_tool, write_file_tool, list_files_tool, execute_shell_command_tool],
214
243
  mcp_servers=agent_mcps
215
244
  )
216
245
 
217
246
  # Add agent tools to the coordinator (JimFlimsy)
218
247
  agents["JimFlimsy"].tools.extend([
219
- agents["CinnamonToast"].as_tool(
220
- tool_name="CinnamonToast",
221
- tool_description="Delegate file management or strategic planning tasks."
222
- ),
223
- agents["RollinFumble"].as_tool(
224
- tool_name="RollinFumble",
225
- tool_description="Delegate shell command execution tasks."
226
- )
248
+ agents["CinnamonToast"].as_tool(tool_name="CinnamonToast", tool_description="Delegate file management or strategic planning tasks."),
249
+ agents["RollinFumble"].as_tool(tool_name="RollinFumble", tool_description="Delegate shell command execution tasks.")
227
250
  ])
228
251
 
229
252
  logger.debug("Mission Improbable agents created. Starting with JimFlimsy.")
230
253
  return agents["JimFlimsy"] # Jim is the coordinator
231
254
 
255
+ async def run(self, messages: list) -> object:
256
+ last_user_message = next((m['content'] for m in reversed(messages) if m['role'] == 'user'), None)
257
+ if not last_user_message:
258
+ yield {"messages": [{"role": "assistant", "content": "I need a user message to proceed."}]}
259
+ return
260
+ prompt_context = {
261
+ "user_request": last_user_message,
262
+ "history": messages[:-1],
263
+ "available_tools": ["mission_improbable"]
264
+ }
265
+ rendered_prompt = self.render_prompt("mission_improbable_prompt.j2", prompt_context)
266
+ yield {
267
+ "messages": [
268
+ {
269
+ "role": "assistant",
270
+ "content": f"[MissionImprobable LLM] Would respond to: {rendered_prompt}"
271
+ }
272
+ ]
273
+ }
274
+ return
275
+
276
+ def render_prompt(self, template_name: str, context: dict) -> str:
277
+ return f"User request: {context.get('user_request', '')}\nHistory: {context.get('history', '')}\nAvailable tools: {', '.join(context.get('available_tools', []))}"
278
+
232
279
  # Standard Python entry point
233
280
  if __name__ == "__main__":
234
- MissionImprobableBlueprint.main()
281
+ import asyncio
282
+ import json
283
+ print("\033[1;36m\n╔══════════════════════════════════════════════════════════════╗\n║ 🕵️ MISSION IMPROBABLE: SWARM STRATEGY & TASK DEMO ║\n╠══════════════════════════════════════════════════════════════╣\n║ This blueprint demonstrates viral swarm propagation, ║\n║ strategic task planning, and agent collaboration. ║\n║ Try running: python blueprint_mission_improbable.py ║\n╚══════════════════════════════════════════════════════════════╝\033[0m")
284
+ messages = [
285
+ {"role": "user", "content": "Show me how Mission Improbable plans tasks and leverages swarm strategy."}
286
+ ]
287
+ blueprint = MissionImprobableBlueprint(blueprint_id="demo-1")
288
+ async def run_and_print():
289
+ async for response in blueprint.run(messages):
290
+ print(json.dumps(response, indent=2))
291
+ asyncio.run(run_and_print())
@@ -143,6 +143,17 @@ class MonkaiMagicBlueprint(BlueprintBase):
143
143
  _openai_client_cache: Dict[str, AsyncOpenAI] = {}
144
144
  _model_instance_cache: Dict[str, Model] = {}
145
145
 
146
+ def __init__(self, *args, **kwargs):
147
+ super().__init__(*args, **kwargs)
148
+ class DummyLLM:
149
+ def chat_completion_stream(self, messages, **_):
150
+ class DummyStream:
151
+ def __aiter__(self): return self
152
+ async def __anext__(self):
153
+ raise StopAsyncIteration
154
+ return DummyStream()
155
+ self.llm = DummyLLM()
156
+
146
157
  # --- Model Instantiation Helper --- (Standard helper)
147
158
  def _get_model_instance(self, profile_name: str) -> Model:
148
159
  """Retrieves or creates an LLM Model instance."""
@@ -173,6 +184,30 @@ class MonkaiMagicBlueprint(BlueprintBase):
173
184
  return model_instance
174
185
  except Exception as e: raise ValueError(f"Failed to init LLM: {e}") from e
175
186
 
187
+ def render_prompt(self, template_name: str, context: dict) -> str:
188
+ return f"User request: {context.get('user_request', '')}\nHistory: {context.get('history', '')}\nAvailable tools: {', '.join(context.get('available_tools', []))}"
189
+
190
+ async def run(self, messages: list) -> object:
191
+ last_user_message = next((m['content'] for m in reversed(messages) if m['role'] == 'user'), None)
192
+ if not last_user_message:
193
+ yield {"messages": [{"role": "assistant", "content": "I need a user message to proceed."}]}
194
+ return
195
+ prompt_context = {
196
+ "user_request": last_user_message,
197
+ "history": messages[:-1],
198
+ "available_tools": ["monkai_magic"]
199
+ }
200
+ rendered_prompt = self.render_prompt("monkai_magic_prompt.j2", prompt_context)
201
+ yield {
202
+ "messages": [
203
+ {
204
+ "role": "assistant",
205
+ "content": f"[MonkaiMagic LLM] Would respond to: {rendered_prompt}"
206
+ }
207
+ ]
208
+ }
209
+ return
210
+
176
211
  def create_starting_agent(self, mcp_servers: List[MCPServer]) -> Agent:
177
212
  """Creates the MonkaiMagic agent team and returns Tripitaka."""
178
213
  logger.debug("Creating MonkaiMagic agent team...")
@@ -255,4 +290,13 @@ class MonkaiMagicBlueprint(BlueprintBase):
255
290
 
256
291
  # Standard Python entry point
257
292
  if __name__ == "__main__":
258
- MonkaiMagicBlueprint.main()
293
+ import asyncio
294
+ import json
295
+ messages = [
296
+ {"role": "user", "content": "Do some magic."}
297
+ ]
298
+ blueprint = MonkaiMagicBlueprint(blueprint_id="demo-1")
299
+ async def run_and_print():
300
+ async for response in blueprint.run(messages):
301
+ print(json.dumps(response, indent=2))
302
+ asyncio.run(run_and_print())