massgen 0.0.3__py3-none-any.whl → 0.1.0__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.

Potentially problematic release.


This version of massgen might be problematic. Click here for more details.

Files changed (268) hide show
  1. massgen/__init__.py +142 -8
  2. massgen/adapters/__init__.py +29 -0
  3. massgen/adapters/ag2_adapter.py +483 -0
  4. massgen/adapters/base.py +183 -0
  5. massgen/adapters/tests/__init__.py +0 -0
  6. massgen/adapters/tests/test_ag2_adapter.py +439 -0
  7. massgen/adapters/tests/test_agent_adapter.py +128 -0
  8. massgen/adapters/utils/__init__.py +2 -0
  9. massgen/adapters/utils/ag2_utils.py +236 -0
  10. massgen/adapters/utils/tests/__init__.py +0 -0
  11. massgen/adapters/utils/tests/test_ag2_utils.py +138 -0
  12. massgen/agent_config.py +329 -55
  13. massgen/api_params_handler/__init__.py +10 -0
  14. massgen/api_params_handler/_api_params_handler_base.py +99 -0
  15. massgen/api_params_handler/_chat_completions_api_params_handler.py +176 -0
  16. massgen/api_params_handler/_claude_api_params_handler.py +113 -0
  17. massgen/api_params_handler/_response_api_params_handler.py +130 -0
  18. massgen/backend/__init__.py +39 -4
  19. massgen/backend/azure_openai.py +385 -0
  20. massgen/backend/base.py +341 -69
  21. massgen/backend/base_with_mcp.py +1102 -0
  22. massgen/backend/capabilities.py +386 -0
  23. massgen/backend/chat_completions.py +577 -130
  24. massgen/backend/claude.py +1033 -537
  25. massgen/backend/claude_code.py +1203 -0
  26. massgen/backend/cli_base.py +209 -0
  27. massgen/backend/docs/BACKEND_ARCHITECTURE.md +126 -0
  28. massgen/backend/{CLAUDE_API_RESEARCH.md → docs/CLAUDE_API_RESEARCH.md} +18 -18
  29. massgen/backend/{GEMINI_API_DOCUMENTATION.md → docs/GEMINI_API_DOCUMENTATION.md} +9 -9
  30. massgen/backend/docs/Gemini MCP Integration Analysis.md +1050 -0
  31. massgen/backend/docs/MCP_IMPLEMENTATION_CLAUDE_BACKEND.md +177 -0
  32. massgen/backend/docs/MCP_INTEGRATION_RESPONSE_BACKEND.md +352 -0
  33. massgen/backend/docs/OPENAI_GPT5_MODELS.md +211 -0
  34. massgen/backend/{OPENAI_RESPONSES_API_FORMAT.md → docs/OPENAI_RESPONSE_API_TOOL_CALLS.md} +3 -3
  35. massgen/backend/docs/OPENAI_response_streaming.md +20654 -0
  36. massgen/backend/docs/inference_backend.md +257 -0
  37. massgen/backend/docs/permissions_and_context_files.md +1085 -0
  38. massgen/backend/external.py +126 -0
  39. massgen/backend/gemini.py +1850 -241
  40. massgen/backend/grok.py +40 -156
  41. massgen/backend/inference.py +156 -0
  42. massgen/backend/lmstudio.py +171 -0
  43. massgen/backend/response.py +1095 -322
  44. massgen/chat_agent.py +131 -113
  45. massgen/cli.py +1560 -275
  46. massgen/config_builder.py +2396 -0
  47. massgen/configs/BACKEND_CONFIGURATION.md +458 -0
  48. massgen/configs/README.md +559 -216
  49. massgen/configs/ag2/ag2_case_study.yaml +27 -0
  50. massgen/configs/ag2/ag2_coder.yaml +34 -0
  51. massgen/configs/ag2/ag2_coder_case_study.yaml +36 -0
  52. massgen/configs/ag2/ag2_gemini.yaml +27 -0
  53. massgen/configs/ag2/ag2_groupchat.yaml +108 -0
  54. massgen/configs/ag2/ag2_groupchat_gpt.yaml +118 -0
  55. massgen/configs/ag2/ag2_single_agent.yaml +21 -0
  56. massgen/configs/basic/multi/fast_timeout_example.yaml +37 -0
  57. massgen/configs/basic/multi/gemini_4o_claude.yaml +31 -0
  58. massgen/configs/basic/multi/gemini_gpt5nano_claude.yaml +36 -0
  59. massgen/configs/{gemini_4o_claude.yaml → basic/multi/geminicode_4o_claude.yaml} +3 -3
  60. massgen/configs/basic/multi/geminicode_gpt5nano_claude.yaml +36 -0
  61. massgen/configs/basic/multi/glm_gemini_claude.yaml +25 -0
  62. massgen/configs/basic/multi/gpt4o_audio_generation.yaml +30 -0
  63. massgen/configs/basic/multi/gpt4o_image_generation.yaml +31 -0
  64. massgen/configs/basic/multi/gpt5nano_glm_qwen.yaml +26 -0
  65. massgen/configs/basic/multi/gpt5nano_image_understanding.yaml +26 -0
  66. massgen/configs/{three_agents_default.yaml → basic/multi/three_agents_default.yaml} +8 -4
  67. massgen/configs/basic/multi/three_agents_opensource.yaml +27 -0
  68. massgen/configs/basic/multi/three_agents_vllm.yaml +20 -0
  69. massgen/configs/basic/multi/two_agents_gemini.yaml +19 -0
  70. massgen/configs/{two_agents.yaml → basic/multi/two_agents_gpt5.yaml} +14 -6
  71. massgen/configs/basic/multi/two_agents_opensource_lmstudio.yaml +31 -0
  72. massgen/configs/basic/multi/two_qwen_vllm_sglang.yaml +28 -0
  73. massgen/configs/{single_agent.yaml → basic/single/single_agent.yaml} +1 -1
  74. massgen/configs/{single_flash2.5.yaml → basic/single/single_flash2.5.yaml} +1 -2
  75. massgen/configs/basic/single/single_gemini2.5pro.yaml +16 -0
  76. massgen/configs/basic/single/single_gpt4o_audio_generation.yaml +22 -0
  77. massgen/configs/basic/single/single_gpt4o_image_generation.yaml +22 -0
  78. massgen/configs/basic/single/single_gpt4o_video_generation.yaml +24 -0
  79. massgen/configs/basic/single/single_gpt5nano.yaml +20 -0
  80. massgen/configs/basic/single/single_gpt5nano_file_search.yaml +18 -0
  81. massgen/configs/basic/single/single_gpt5nano_image_understanding.yaml +17 -0
  82. massgen/configs/basic/single/single_gptoss120b.yaml +15 -0
  83. massgen/configs/basic/single/single_openrouter_audio_understanding.yaml +15 -0
  84. massgen/configs/basic/single/single_qwen_video_understanding.yaml +15 -0
  85. massgen/configs/debug/code_execution/command_filtering_blacklist.yaml +29 -0
  86. massgen/configs/debug/code_execution/command_filtering_whitelist.yaml +28 -0
  87. massgen/configs/debug/code_execution/docker_verification.yaml +29 -0
  88. massgen/configs/debug/skip_coordination_test.yaml +27 -0
  89. massgen/configs/debug/test_sdk_migration.yaml +17 -0
  90. massgen/configs/docs/DISCORD_MCP_SETUP.md +208 -0
  91. massgen/configs/docs/TWITTER_MCP_ENESCINAR_SETUP.md +82 -0
  92. massgen/configs/providers/azure/azure_openai_multi.yaml +21 -0
  93. massgen/configs/providers/azure/azure_openai_single.yaml +19 -0
  94. massgen/configs/providers/claude/claude.yaml +14 -0
  95. massgen/configs/providers/gemini/gemini_gpt5nano.yaml +28 -0
  96. massgen/configs/providers/local/lmstudio.yaml +11 -0
  97. massgen/configs/providers/openai/gpt5.yaml +46 -0
  98. massgen/configs/providers/openai/gpt5_nano.yaml +46 -0
  99. massgen/configs/providers/others/grok_single_agent.yaml +19 -0
  100. massgen/configs/providers/others/zai_coding_team.yaml +108 -0
  101. massgen/configs/providers/others/zai_glm45.yaml +12 -0
  102. massgen/configs/{creative_team.yaml → teams/creative/creative_team.yaml} +16 -6
  103. massgen/configs/{travel_planning.yaml → teams/creative/travel_planning.yaml} +16 -6
  104. massgen/configs/{news_analysis.yaml → teams/research/news_analysis.yaml} +16 -6
  105. massgen/configs/{research_team.yaml → teams/research/research_team.yaml} +15 -7
  106. massgen/configs/{technical_analysis.yaml → teams/research/technical_analysis.yaml} +16 -6
  107. massgen/configs/tools/code-execution/basic_command_execution.yaml +25 -0
  108. massgen/configs/tools/code-execution/code_execution_use_case_simple.yaml +41 -0
  109. massgen/configs/tools/code-execution/docker_claude_code.yaml +32 -0
  110. massgen/configs/tools/code-execution/docker_multi_agent.yaml +32 -0
  111. massgen/configs/tools/code-execution/docker_simple.yaml +29 -0
  112. massgen/configs/tools/code-execution/docker_with_resource_limits.yaml +32 -0
  113. massgen/configs/tools/code-execution/multi_agent_playwright_automation.yaml +57 -0
  114. massgen/configs/tools/filesystem/cc_gpt5_gemini_filesystem.yaml +34 -0
  115. massgen/configs/tools/filesystem/claude_code_context_sharing.yaml +68 -0
  116. massgen/configs/tools/filesystem/claude_code_flash2.5.yaml +43 -0
  117. massgen/configs/tools/filesystem/claude_code_flash2.5_gptoss.yaml +49 -0
  118. massgen/configs/tools/filesystem/claude_code_gpt5nano.yaml +31 -0
  119. massgen/configs/tools/filesystem/claude_code_single.yaml +40 -0
  120. massgen/configs/tools/filesystem/fs_permissions_test.yaml +87 -0
  121. massgen/configs/tools/filesystem/gemini_gemini_workspace_cleanup.yaml +54 -0
  122. massgen/configs/tools/filesystem/gemini_gpt5_filesystem_casestudy.yaml +30 -0
  123. massgen/configs/tools/filesystem/gemini_gpt5nano_file_context_path.yaml +43 -0
  124. massgen/configs/tools/filesystem/gemini_gpt5nano_protected_paths.yaml +45 -0
  125. massgen/configs/tools/filesystem/gpt5mini_cc_fs_context_path.yaml +31 -0
  126. massgen/configs/tools/filesystem/grok4_gpt5_gemini_filesystem.yaml +32 -0
  127. massgen/configs/tools/filesystem/multiturn/grok4_gpt5_claude_code_filesystem_multiturn.yaml +58 -0
  128. massgen/configs/tools/filesystem/multiturn/grok4_gpt5_gemini_filesystem_multiturn.yaml +58 -0
  129. massgen/configs/tools/filesystem/multiturn/two_claude_code_filesystem_multiturn.yaml +47 -0
  130. massgen/configs/tools/filesystem/multiturn/two_gemini_flash_filesystem_multiturn.yaml +48 -0
  131. massgen/configs/tools/mcp/claude_code_discord_mcp_example.yaml +27 -0
  132. massgen/configs/tools/mcp/claude_code_simple_mcp.yaml +35 -0
  133. massgen/configs/tools/mcp/claude_code_twitter_mcp_example.yaml +32 -0
  134. massgen/configs/tools/mcp/claude_mcp_example.yaml +24 -0
  135. massgen/configs/tools/mcp/claude_mcp_test.yaml +27 -0
  136. massgen/configs/tools/mcp/five_agents_travel_mcp_test.yaml +157 -0
  137. massgen/configs/tools/mcp/five_agents_weather_mcp_test.yaml +103 -0
  138. massgen/configs/tools/mcp/gemini_mcp_example.yaml +24 -0
  139. massgen/configs/tools/mcp/gemini_mcp_filesystem_test.yaml +23 -0
  140. massgen/configs/tools/mcp/gemini_mcp_filesystem_test_sharing.yaml +23 -0
  141. massgen/configs/tools/mcp/gemini_mcp_filesystem_test_single_agent.yaml +17 -0
  142. massgen/configs/tools/mcp/gemini_mcp_filesystem_test_with_claude_code.yaml +24 -0
  143. massgen/configs/tools/mcp/gemini_mcp_test.yaml +27 -0
  144. massgen/configs/tools/mcp/gemini_notion_mcp.yaml +52 -0
  145. massgen/configs/tools/mcp/gpt5_nano_mcp_example.yaml +24 -0
  146. massgen/configs/tools/mcp/gpt5_nano_mcp_test.yaml +27 -0
  147. massgen/configs/tools/mcp/gpt5mini_claude_code_discord_mcp_example.yaml +38 -0
  148. massgen/configs/tools/mcp/gpt_oss_mcp_example.yaml +25 -0
  149. massgen/configs/tools/mcp/gpt_oss_mcp_test.yaml +28 -0
  150. massgen/configs/tools/mcp/grok3_mini_mcp_example.yaml +24 -0
  151. massgen/configs/tools/mcp/grok3_mini_mcp_test.yaml +27 -0
  152. massgen/configs/tools/mcp/multimcp_gemini.yaml +111 -0
  153. massgen/configs/tools/mcp/qwen_api_mcp_example.yaml +25 -0
  154. massgen/configs/tools/mcp/qwen_api_mcp_test.yaml +28 -0
  155. massgen/configs/tools/mcp/qwen_local_mcp_example.yaml +24 -0
  156. massgen/configs/tools/mcp/qwen_local_mcp_test.yaml +27 -0
  157. massgen/configs/tools/planning/five_agents_discord_mcp_planning_mode.yaml +140 -0
  158. massgen/configs/tools/planning/five_agents_filesystem_mcp_planning_mode.yaml +151 -0
  159. massgen/configs/tools/planning/five_agents_notion_mcp_planning_mode.yaml +151 -0
  160. massgen/configs/tools/planning/five_agents_twitter_mcp_planning_mode.yaml +155 -0
  161. massgen/configs/tools/planning/gpt5_mini_case_study_mcp_planning_mode.yaml +73 -0
  162. massgen/configs/tools/web-search/claude_streamable_http_test.yaml +43 -0
  163. massgen/configs/tools/web-search/gemini_streamable_http_test.yaml +43 -0
  164. massgen/configs/tools/web-search/gpt5_mini_streamable_http_test.yaml +43 -0
  165. massgen/configs/tools/web-search/gpt_oss_streamable_http_test.yaml +44 -0
  166. massgen/configs/tools/web-search/grok3_mini_streamable_http_test.yaml +43 -0
  167. massgen/configs/tools/web-search/qwen_api_streamable_http_test.yaml +44 -0
  168. massgen/configs/tools/web-search/qwen_local_streamable_http_test.yaml +43 -0
  169. massgen/coordination_tracker.py +708 -0
  170. massgen/docker/README.md +462 -0
  171. massgen/filesystem_manager/__init__.py +21 -0
  172. massgen/filesystem_manager/_base.py +9 -0
  173. massgen/filesystem_manager/_code_execution_server.py +545 -0
  174. massgen/filesystem_manager/_docker_manager.py +477 -0
  175. massgen/filesystem_manager/_file_operation_tracker.py +248 -0
  176. massgen/filesystem_manager/_filesystem_manager.py +813 -0
  177. massgen/filesystem_manager/_path_permission_manager.py +1261 -0
  178. massgen/filesystem_manager/_workspace_tools_server.py +1815 -0
  179. massgen/formatter/__init__.py +10 -0
  180. massgen/formatter/_chat_completions_formatter.py +284 -0
  181. massgen/formatter/_claude_formatter.py +235 -0
  182. massgen/formatter/_formatter_base.py +156 -0
  183. massgen/formatter/_response_formatter.py +263 -0
  184. massgen/frontend/__init__.py +1 -2
  185. massgen/frontend/coordination_ui.py +471 -286
  186. massgen/frontend/displays/base_display.py +56 -11
  187. massgen/frontend/displays/create_coordination_table.py +1956 -0
  188. massgen/frontend/displays/rich_terminal_display.py +1259 -619
  189. massgen/frontend/displays/simple_display.py +9 -4
  190. massgen/frontend/displays/terminal_display.py +27 -68
  191. massgen/logger_config.py +681 -0
  192. massgen/mcp_tools/README.md +232 -0
  193. massgen/mcp_tools/__init__.py +105 -0
  194. massgen/mcp_tools/backend_utils.py +1035 -0
  195. massgen/mcp_tools/circuit_breaker.py +195 -0
  196. massgen/mcp_tools/client.py +894 -0
  197. massgen/mcp_tools/config_validator.py +138 -0
  198. massgen/mcp_tools/docs/circuit_breaker.md +646 -0
  199. massgen/mcp_tools/docs/client.md +950 -0
  200. massgen/mcp_tools/docs/config_validator.md +478 -0
  201. massgen/mcp_tools/docs/exceptions.md +1165 -0
  202. massgen/mcp_tools/docs/security.md +854 -0
  203. massgen/mcp_tools/exceptions.py +338 -0
  204. massgen/mcp_tools/hooks.py +212 -0
  205. massgen/mcp_tools/security.py +780 -0
  206. massgen/message_templates.py +342 -64
  207. massgen/orchestrator.py +1515 -241
  208. massgen/stream_chunk/__init__.py +35 -0
  209. massgen/stream_chunk/base.py +92 -0
  210. massgen/stream_chunk/multimodal.py +237 -0
  211. massgen/stream_chunk/text.py +162 -0
  212. massgen/tests/mcp_test_server.py +150 -0
  213. massgen/tests/multi_turn_conversation_design.md +0 -8
  214. massgen/tests/test_azure_openai_backend.py +156 -0
  215. massgen/tests/test_backend_capabilities.py +262 -0
  216. massgen/tests/test_backend_event_loop_all.py +179 -0
  217. massgen/tests/test_chat_completions_refactor.py +142 -0
  218. massgen/tests/test_claude_backend.py +15 -28
  219. massgen/tests/test_claude_code.py +268 -0
  220. massgen/tests/test_claude_code_context_sharing.py +233 -0
  221. massgen/tests/test_claude_code_orchestrator.py +175 -0
  222. massgen/tests/test_cli_backends.py +180 -0
  223. massgen/tests/test_code_execution.py +679 -0
  224. massgen/tests/test_external_agent_backend.py +134 -0
  225. massgen/tests/test_final_presentation_fallback.py +237 -0
  226. massgen/tests/test_gemini_planning_mode.py +351 -0
  227. massgen/tests/test_grok_backend.py +7 -10
  228. massgen/tests/test_http_mcp_server.py +42 -0
  229. massgen/tests/test_integration_simple.py +198 -0
  230. massgen/tests/test_mcp_blocking.py +125 -0
  231. massgen/tests/test_message_context_building.py +29 -47
  232. massgen/tests/test_orchestrator_final_presentation.py +48 -0
  233. massgen/tests/test_path_permission_manager.py +2087 -0
  234. massgen/tests/test_rich_terminal_display.py +14 -13
  235. massgen/tests/test_timeout.py +133 -0
  236. massgen/tests/test_v3_3agents.py +11 -12
  237. massgen/tests/test_v3_simple.py +8 -13
  238. massgen/tests/test_v3_three_agents.py +11 -18
  239. massgen/tests/test_v3_two_agents.py +8 -13
  240. massgen/token_manager/__init__.py +7 -0
  241. massgen/token_manager/token_manager.py +400 -0
  242. massgen/utils.py +52 -16
  243. massgen/v1/agent.py +45 -91
  244. massgen/v1/agents.py +18 -53
  245. massgen/v1/backends/gemini.py +50 -153
  246. massgen/v1/backends/grok.py +21 -54
  247. massgen/v1/backends/oai.py +39 -111
  248. massgen/v1/cli.py +36 -93
  249. massgen/v1/config.py +8 -12
  250. massgen/v1/logging.py +43 -127
  251. massgen/v1/main.py +18 -32
  252. massgen/v1/orchestrator.py +68 -209
  253. massgen/v1/streaming_display.py +62 -163
  254. massgen/v1/tools.py +8 -12
  255. massgen/v1/types.py +9 -23
  256. massgen/v1/utils.py +5 -23
  257. massgen-0.1.0.dist-info/METADATA +1245 -0
  258. massgen-0.1.0.dist-info/RECORD +273 -0
  259. massgen-0.1.0.dist-info/entry_points.txt +2 -0
  260. massgen/frontend/logging/__init__.py +0 -9
  261. massgen/frontend/logging/realtime_logger.py +0 -197
  262. massgen-0.0.3.dist-info/METADATA +0 -568
  263. massgen-0.0.3.dist-info/RECORD +0 -76
  264. massgen-0.0.3.dist-info/entry_points.txt +0 -2
  265. /massgen/backend/{Function calling openai responses.md → docs/Function calling openai responses.md} +0 -0
  266. {massgen-0.0.3.dist-info → massgen-0.1.0.dist-info}/WHEEL +0 -0
  267. {massgen-0.0.3.dist-info → massgen-0.1.0.dist-info}/licenses/LICENSE +0 -0
  268. {massgen-0.0.3.dist-info → massgen-0.1.0.dist-info}/top_level.txt +0 -0
massgen/v1/agent.py CHANGED
@@ -1,19 +1,18 @@
1
- import os
2
- import sys
3
- import time
1
+ # -*- coding: utf-8 -*-
4
2
  import json
5
- from typing import Callable, Union, Optional, List, Dict
6
- from concurrent.futures import ThreadPoolExecutor, TimeoutError as FutureTimeoutError
3
+ import time
4
+ from abc import ABC
5
+ from concurrent.futures import ThreadPoolExecutor
6
+ from concurrent.futures import TimeoutError as FutureTimeoutError
7
+ from typing import Any, Callable, Dict, List, Optional
7
8
 
8
9
  from dotenv import load_dotenv
9
10
 
10
- load_dotenv()
11
+ from .backends import gemini, grok, oai
12
+ from .types import AgentResponse, AgentState, ModelConfig, TaskInput
13
+ from .utils import function_to_json, get_agent_type_from_model
11
14
 
12
- from .types import TaskInput, AgentState, AgentResponse, ModelConfig
13
- from .utils import get_agent_type_from_model, function_to_json
14
- from abc import ABC, abstractmethod
15
- from typing import Any, Callable, Union, Optional, List, Dict
16
- from .backends import oai, gemini, grok
15
+ load_dotenv()
17
16
 
18
17
  # TASK_INSTRUCTION = """
19
18
  # Please use your expertise and tools (if available) to fully verify if the best CURRENT ANSWER addresses the ORIGINAL MESSAGE.
@@ -24,7 +23,7 @@ from .backends import oai, gemini, grok
24
23
  # """
25
24
 
26
25
  SYSTEM_INSTRUCTION = f"""
27
- You are evaluating answers from multiple agents for final response to a message.
26
+ You are evaluating answers from multiple agents for final response to a message.
28
27
 
29
28
  For every aspect, claim, reasoning steps in the CURRENT ANSWERS, verify correctness, factual accuracy, and completeness using your expertise, reasoning, and available tools.
30
29
 
@@ -111,9 +110,7 @@ class MassAgent(ABC):
111
110
  "grok": grok.process_message,
112
111
  }
113
112
  if self.agent_type not in process_message_impl_map:
114
- raise ValueError(
115
- f"Unknown agent type: {self.agent_type}. Available types: {list(process_message_impl_map.keys())}"
116
- )
113
+ raise ValueError(f"Unknown agent type: {self.agent_type}. Available types: {list(process_message_impl_map.keys())}")
117
114
 
118
115
  # Get the appropriate process_message implementation based on the agent type
119
116
  self.process_message_impl = process_message_impl_map[self.agent_type]
@@ -130,9 +127,7 @@ class MassAgent(ABC):
130
127
  self.stream_callback = stream_callback
131
128
  self.kwargs = kwargs
132
129
 
133
- def process_message(
134
- self, messages: List[Dict[str, str]], tools: List[str] = None
135
- ) -> AgentResponse:
130
+ def process_message(self, messages: List[Dict[str, str]], tools: List[str] = None) -> AgentResponse:
136
131
  """
137
132
  Core LLM inference function for task processing.
138
133
 
@@ -164,9 +159,7 @@ class MassAgent(ABC):
164
159
  try:
165
160
  # Use ThreadPoolExecutor to implement timeout
166
161
  with ThreadPoolExecutor(max_workers=1) as executor:
167
- future = executor.submit(
168
- self.process_message_impl, messages=messages, tools=tools, **config
169
- )
162
+ future = executor.submit(self.process_message_impl, messages=messages, tools=tools, **config)
170
163
 
171
164
  try:
172
165
  # Wait for result with timeout
@@ -202,11 +195,9 @@ class MassAgent(ABC):
202
195
  """
203
196
  # Use the orchestrator to update the answer and notify other agents to restart
204
197
  self.orchestrator.notify_answer_update(self.agent_id, new_answer)
205
- return f"The new answer has been added."
198
+ return "The new answer has been added."
206
199
 
207
- def vote(
208
- self, agent_id: int, reason: str = "", invalid_vote_options: List[int] = []
209
- ):
200
+ def vote(self, agent_id: int, reason: str = "", invalid_vote_options: List[int] = []):
210
201
  """
211
202
  Vote for the representative agent, who you believe has found the correct solution.
212
203
 
@@ -255,9 +246,7 @@ class MassAgent(ABC):
255
246
  deduplicated_function_calls.append(func_call)
256
247
  return deduplicated_function_calls
257
248
 
258
- def _execute_function_calls(
259
- self, function_calls: List[Dict], invalid_vote_options: List[int] = []
260
- ):
249
+ def _execute_function_calls(self, function_calls: List[Dict], invalid_vote_options: List[int] = []):
261
250
  """Execute function calls and return function outputs."""
262
251
  from .tools import register_tool
263
252
 
@@ -311,9 +300,7 @@ class MassAgent(ABC):
311
300
 
312
301
  # DEBUGGING
313
302
  with open("function_calls.txt", "a") as f:
314
- f.write(
315
- f"[{time.strftime('%Y-%m-%d %H:%M:%S')}] Agent {self.agent_id} ({self.model}):\n"
316
- )
303
+ f.write(f"[{time.strftime('%Y-%m-%d %H:%M:%S')}] Agent {self.agent_id} ({self.model}):\n")
317
304
  f.write(f"{json.dumps(error_output, indent=2)}\n")
318
305
  f.write(f"Successful called: {False}\n")
319
306
 
@@ -335,7 +322,7 @@ class MassAgent(ABC):
335
322
  "new_answer": {
336
323
  "type": "string",
337
324
  "description": "Your new answer, which should be self-contained, complete, and ready to serve as the definitive final response.",
338
- }
325
+ },
339
326
  },
340
327
  "required": ["new_answer"],
341
328
  },
@@ -360,16 +347,8 @@ class MassAgent(ABC):
360
347
  },
361
348
  }
362
349
  # Check if there are any available options to vote for. If not, only return the add_answer schema.
363
- available_options = [
364
- agent_id
365
- for agent_id, agent_state in self.orchestrator.agent_states.items()
366
- if agent_state.curr_answer
367
- ]
368
- return (
369
- [add_answer_schema, vote_schema]
370
- if available_options
371
- else [add_answer_schema]
372
- )
350
+ available_options = [agent_id for agent_id, agent_state in self.orchestrator.agent_states.items() if agent_state.curr_answer]
351
+ return [add_answer_schema, vote_schema] if available_options else [add_answer_schema]
373
352
 
374
353
  def _get_registered_tools(self) -> List[Dict[str, Any]]:
375
354
  """Return the tool schema for the tools that are available to this agent."""
@@ -420,9 +399,7 @@ class MassAgent(ABC):
420
399
  agent_votes = []
421
400
  for agent_id, agent_state in self.orchestrator.agent_states.items():
422
401
  if agent_state.curr_vote:
423
- agent_votes.append(
424
- f"**Vote for Agent {agent_state.curr_vote.target_id}**: {agent_state.curr_vote.reason}"
425
- )
402
+ agent_votes.append(f"**Vote for Agent {agent_state.curr_vote.target_id}**: {agent_state.curr_vote.reason}")
426
403
  return agent_votes
427
404
 
428
405
  def _get_task_input(self, task: TaskInput) -> str:
@@ -440,11 +417,7 @@ class MassAgent(ABC):
440
417
  all_agent_answers = self._get_all_answers()
441
418
  all_agent_answers_str = "\n\n".join(all_agent_answers)
442
419
  # Check if in debate mode or not
443
- voted_agents = [
444
- agent_id
445
- for agent_id, agent_state in self.orchestrator.agent_states.items()
446
- if agent_state.curr_vote is not None
447
- ]
420
+ voted_agents = [agent_id for agent_id, agent_state in self.orchestrator.agent_states.items() if agent_state.curr_vote is not None]
448
421
  if len(voted_agents) == len(self.orchestrator.agent_states):
449
422
  # Case 2: All agents have voted and are debating. Can not use agent status to check as they have been updated to 'working/debate'
450
423
  all_agent_votes = self._get_all_votes()
@@ -458,9 +431,7 @@ class MassAgent(ABC):
458
431
  else:
459
432
  # Case 3: All agents are working and not in debating
460
433
  status = "working"
461
- task_input = AGENT_ANSWER_MESSAGE.format(
462
- task=task.question, agent_answers=all_agent_answers_str
463
- )
434
+ task_input = AGENT_ANSWER_MESSAGE.format(task=task.question, agent_answers=all_agent_answers_str)
464
435
 
465
436
  return status, task_input
466
437
 
@@ -500,17 +471,13 @@ class MassAgent(ABC):
500
471
 
501
472
  # Initialize working messages
502
473
  curr_round = 0
503
- working_status, working_messages, all_tools = self._get_curr_messages_and_tools(
504
- task
505
- )
474
+ working_status, working_messages, all_tools = self._get_curr_messages_and_tools(task)
506
475
 
507
476
  # Start the task solving loop
508
477
  while curr_round < self.max_rounds and self.state.status == "working":
509
478
  try:
510
479
  # Call LLM with current conversation
511
- result = self.process_message(
512
- messages=working_messages, tools=all_tools
513
- )
480
+ result = self.process_message(messages=working_messages, tools=all_tools)
514
481
 
515
482
  # Before Making the new result into effect, check if there is any update from other agents that are unseen by this agent
516
483
  agents_with_update = self.check_update()
@@ -521,30 +488,19 @@ class MassAgent(ABC):
521
488
 
522
489
  # Add assistant response
523
490
  if result.text:
524
- working_messages.append(
525
- {"role": "assistant", "content": result.text}
526
- )
491
+ working_messages.append({"role": "assistant", "content": result.text})
527
492
 
528
493
  # Execute function calls if any
529
494
  if result.function_calls:
530
495
  # Deduplicate function calls by their name
531
- result.function_calls = self.deduplicate_function_calls(
532
- result.function_calls
533
- )
496
+ result.function_calls = self.deduplicate_function_calls(result.function_calls)
534
497
  # Not voting if there is any update
535
- function_outputs, successful_called = self._execute_function_calls(
536
- result.function_calls, invalid_vote_options=agents_with_update
537
- )
498
+ function_outputs, successful_called = self._execute_function_calls(result.function_calls, invalid_vote_options=agents_with_update)
538
499
 
539
500
  renew_conversation = False
540
- for function_call, function_output, successful_called in zip(
541
- result.function_calls, function_outputs, successful_called
542
- ):
501
+ for function_call, function_output, successful_called in zip(result.function_calls, function_outputs, successful_called):
543
502
  # If call `add_answer`, we need to rebuild the conversation history with new answers
544
- if (
545
- function_call.get("name") == "add_answer"
546
- and successful_called
547
- ):
503
+ if function_call.get("name") == "add_answer" and successful_called:
548
504
  renew_conversation = True
549
505
  break
550
506
 
@@ -553,17 +509,15 @@ class MassAgent(ABC):
553
509
  renew_conversation = True
554
510
  break
555
511
 
556
- if (
557
- not renew_conversation
558
- ): # Add all function call results to the current conversation and continue the loop
559
- for function_call, function_output in zip(
560
- result.function_calls, function_outputs
561
- ):
512
+ if not renew_conversation: # Add all function call results to the current conversation and continue the loop
513
+ for function_call, function_output in zip(result.function_calls, function_outputs):
562
514
  working_messages.extend([function_call, function_output])
563
515
  else: # Renew the conversation
564
- working_status, working_messages, all_tools = (
565
- self._get_curr_messages_and_tools(task)
566
- )
516
+ (
517
+ working_status,
518
+ working_messages,
519
+ all_tools,
520
+ ) = self._get_curr_messages_and_tools(task)
567
521
  else:
568
522
  # No function calls - check if we should continue or stop
569
523
  if self.state.status == "voted":
@@ -573,15 +527,17 @@ class MassAgent(ABC):
573
527
  # Check if there is any update from other agents that are unseen by this agent
574
528
  if has_update and working_status != "initial":
575
529
  # The vote option has changed, thus we need to renew the conversation within the loop
576
- working_status, working_messages, all_tools = (
577
- self._get_curr_messages_and_tools(task)
578
- )
530
+ (
531
+ working_status,
532
+ working_messages,
533
+ all_tools,
534
+ ) = self._get_curr_messages_and_tools(task)
579
535
  else: # Continue the current conversation and prompting checkin
580
536
  working_messages.append(
581
537
  {
582
538
  "role": "user",
583
539
  "content": "Finish your work above by making a tool call of `vote` or `add_answer`. Make sure you actually call the tool.",
584
- }
540
+ },
585
541
  )
586
542
 
587
543
  curr_round += 1
@@ -592,9 +548,7 @@ class MassAgent(ABC):
592
548
  break
593
549
 
594
550
  except Exception as e:
595
- print(
596
- f"❌ Agent {self.agent_id} error in round {self.state.chat_round}: {e}"
597
- )
551
+ print(f"❌ Agent {self.agent_id} error in round {self.state.chat_round}: {e}")
598
552
  if self.orchestrator:
599
553
  self.orchestrator.mark_agent_failed(self.agent_id, str(e))
600
554
 
massgen/v1/agents.py CHANGED
@@ -1,3 +1,4 @@
1
+ # -*- coding: utf-8 -*-
1
2
  """
2
3
  MassAgent implementations that wrap the existing agent backends.
3
4
 
@@ -5,20 +6,14 @@ This module provides MassAgent-compatible wrappers for the existing
5
6
  OpenAI, Gemini, and Grok agent implementations.
6
7
  """
7
8
 
8
- import os
9
- import sys
10
- import copy
11
- import time
12
- import traceback
13
- from typing import Callable, Union, Optional, List, Dict, Any
9
+ from typing import Callable, Dict, List, Optional
14
10
 
15
11
  from dotenv import load_dotenv
16
12
 
17
- load_dotenv()
18
-
19
13
  from .agent import MassAgent
20
14
  from .types import ModelConfig, TaskInput
21
- from .tools import register_tool
15
+
16
+ load_dotenv()
22
17
 
23
18
 
24
19
  class OpenAIMassAgent(MassAgent):
@@ -32,7 +27,6 @@ class OpenAIMassAgent(MassAgent):
32
27
  stream_callback: Optional[Callable] = None,
33
28
  **kwargs,
34
29
  ):
35
-
36
30
  # Pass all configuration to parent, including agent_type
37
31
  super().__init__(
38
32
  agent_id=agent_id,
@@ -54,7 +48,6 @@ class GrokMassAgent(OpenAIMassAgent):
54
48
  stream_callback: Optional[Callable] = None,
55
49
  **kwargs,
56
50
  ):
57
-
58
51
  # Pass all configuration to parent, including agent_type
59
52
  super().__init__(
60
53
  agent_id=agent_id,
@@ -76,7 +69,6 @@ class GeminiMassAgent(OpenAIMassAgent):
76
69
  stream_callback: Optional[Callable] = None,
77
70
  **kwargs,
78
71
  ):
79
-
80
72
  # Pass all configuration to parent, including agent_type
81
73
  super().__init__(
82
74
  agent_id=agent_id,
@@ -157,19 +149,13 @@ class GeminiMassAgent(OpenAIMassAgent):
157
149
  if working_messages[-1].get("role", "") == "user":
158
150
  if not function_call_enabled:
159
151
  working_messages[-1]["content"] += (
160
- "\n\n"
161
- + "Note that the `add_answer` and `vote` tools are not enabled now. Please prioritize using the built-in tools to analyze the task first."
152
+ "\n\n" + "Note that the `add_answer` and `vote` tools are not enabled now. Please prioritize using the built-in tools to analyze the task first."
162
153
  )
163
154
  else:
164
- working_messages[-1]["content"] += (
165
- "\n\n"
166
- + "Note that the `add_answer` and `vote` tools are enabled now."
167
- )
155
+ working_messages[-1]["content"] += "\n\n" + "Note that the `add_answer` and `vote` tools are enabled now."
168
156
 
169
157
  # Call LLM with current conversation
170
- result = self.process_message(
171
- messages=working_messages, tools=available_tools
172
- )
158
+ result = self.process_message(messages=working_messages, tools=available_tools)
173
159
 
174
160
  # Before Making the new result into effect, check if there is any update from other agents that are unseen by this agent
175
161
  agents_with_update = self.check_update()
@@ -180,29 +166,18 @@ class GeminiMassAgent(OpenAIMassAgent):
180
166
 
181
167
  # Add assistant response
182
168
  if result.text:
183
- working_messages.append(
184
- {"role": "assistant", "content": result.text}
185
- )
169
+ working_messages.append({"role": "assistant", "content": result.text})
186
170
 
187
171
  # Execute function calls if any
188
172
  if result.function_calls:
189
173
  # Deduplicate function calls by their name
190
- result.function_calls = self.deduplicate_function_calls(
191
- result.function_calls
192
- )
193
- function_outputs, successful_called = self._execute_function_calls(
194
- result.function_calls, invalid_vote_options=agents_with_update
195
- )
174
+ result.function_calls = self.deduplicate_function_calls(result.function_calls)
175
+ function_outputs, successful_called = self._execute_function_calls(result.function_calls, invalid_vote_options=agents_with_update)
196
176
 
197
177
  renew_conversation = False
198
- for function_call, function_output, successful_called in zip(
199
- result.function_calls, function_outputs, successful_called
200
- ):
178
+ for function_call, function_output, successful_called in zip(result.function_calls, function_outputs, successful_called):
201
179
  # If call `add_answer`, we need to rebuild the conversation history with new answers
202
- if (
203
- function_call.get("name") == "add_answer"
204
- and successful_called
205
- ):
180
+ if function_call.get("name") == "add_answer" and successful_called:
206
181
  renew_conversation = True
207
182
  break
208
183
 
@@ -213,17 +188,13 @@ class GeminiMassAgent(OpenAIMassAgent):
213
188
 
214
189
  if not renew_conversation:
215
190
  # Add all function call results to the current conversation
216
- for function_call, function_output in zip(
217
- result.function_calls, function_outputs
218
- ):
191
+ for function_call, function_output in zip(result.function_calls, function_outputs):
219
192
  working_messages.extend([function_call, function_output])
220
193
  # If we have used custom tools, switch to built-in tools in the next round
221
194
  if tool_switch:
222
195
  available_tools = built_in_tools
223
196
  function_call_enabled = False
224
- print(
225
- f"🔄 Agent {self.agent_id} (Gemini) switching to built-in tools in the next round"
226
- )
197
+ print(f"🔄 Agent {self.agent_id} (Gemini) switching to built-in tools in the next round")
227
198
  else: # Renew the conversation
228
199
  (
229
200
  working_status,
@@ -259,16 +230,14 @@ class GeminiMassAgent(OpenAIMassAgent):
259
230
  {
260
231
  "role": "user",
261
232
  "content": "Finish your work above by making a tool call of `vote` or `add_answer`. Make sure you actually call the tool.",
262
- }
233
+ },
263
234
  )
264
235
 
265
236
  # Switch to custom tools in the next round
266
237
  if tool_switch:
267
238
  available_tools = system_tools + custom_tools
268
239
  function_call_enabled = True
269
- print(
270
- f"🔄 Agent {self.agent_id} (Gemini) switching to custom tools in the next round"
271
- )
240
+ print(f"🔄 Agent {self.agent_id} (Gemini) switching to custom tools in the next round")
272
241
 
273
242
  curr_round += 1
274
243
  self.state.chat_round += 1
@@ -278,9 +247,7 @@ class GeminiMassAgent(OpenAIMassAgent):
278
247
  break
279
248
 
280
249
  except Exception as e:
281
- print(
282
- f"❌ Agent {self.agent_id} error in round {self.state.chat_round}: {e}"
283
- )
250
+ print(f"❌ Agent {self.agent_id} error in round {self.state.chat_round}: {e}")
284
251
  if self.orchestrator:
285
252
  self.orchestrator.mark_agent_failed(self.agent_id, str(e))
286
253
 
@@ -318,9 +285,7 @@ def create_agent(
318
285
  }
319
286
 
320
287
  if agent_type not in agent_classes:
321
- raise ValueError(
322
- f"Unknown agent type: {agent_type}. Available types: {list(agent_classes.keys())}"
323
- )
288
+ raise ValueError(f"Unknown agent type: {agent_type}. Available types: {list(agent_classes.keys())}")
324
289
 
325
290
  return agent_classes[agent_type](
326
291
  agent_id=agent_id,