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/logging.py CHANGED
@@ -1,3 +1,4 @@
1
+ # -*- coding: utf-8 -*-
1
2
  """
2
3
  MassGen Logging System
3
4
 
@@ -6,19 +7,17 @@ recording all agent state changes, orchestration events, and system activities
6
7
  to local files for detailed analysis.
7
8
  """
8
9
 
9
- import os
10
10
  import json
11
- import time
12
11
  import logging
12
+ import os
13
13
  import threading
14
+ import time
15
+ from collections import Counter
14
16
  from datetime import datetime
15
- from typing import Dict, Any, List, Optional, Union
16
17
  from pathlib import Path
17
- from dataclasses import dataclass, field, asdict
18
- from collections import Counter
19
- import textwrap
18
+ from typing import Any, Dict, List, Optional
20
19
 
21
- from .types import LogEntry, AnswerRecord, VoteRecord
20
+ from .types import AnswerRecord, LogEntry, VoteRecord
22
21
 
23
22
 
24
23
  class MassLogManager:
@@ -65,7 +64,7 @@ class MassLogManager:
65
64
  self.non_blocking = non_blocking
66
65
 
67
66
  if self.non_blocking:
68
- print(f"⚠️ LOGGING: Non-blocking mode enabled - file logging disabled")
67
+ print("⚠️ LOGGING: Non-blocking mode enabled - file logging disabled")
69
68
 
70
69
  # Create main session directory
71
70
  self.session_dir = self.base_log_dir / self.session_id
@@ -73,9 +72,7 @@ class MassLogManager:
73
72
  try:
74
73
  self.session_dir.mkdir(parents=True, exist_ok=True)
75
74
  except Exception as e:
76
- print(
77
- f"Warning: Failed to create session directory, enabling non-blocking mode: {e}"
78
- )
75
+ print(f"Warning: Failed to create session directory, enabling non-blocking mode: {e}")
79
76
  self.non_blocking = True
80
77
 
81
78
  # Create subdirectories
@@ -89,9 +86,7 @@ class MassLogManager:
89
86
  self.answers_dir.mkdir(exist_ok=True)
90
87
  self.votes_dir.mkdir(exist_ok=True)
91
88
  except Exception as e:
92
- print(
93
- f"Warning: Failed to create subdirectories, enabling non-blocking mode: {e}"
94
- )
89
+ print(f"Warning: Failed to create subdirectories, enabling non-blocking mode: {e}")
95
90
  self.non_blocking = True
96
91
 
97
92
  # File paths
@@ -146,11 +141,9 @@ class MassLogManager:
146
141
 
147
142
  try:
148
143
  with open(self.system_log_file, "w", encoding="utf-8") as f:
149
- f.write(f"MassGen System Messages Log\n")
144
+ f.write("MassGen System Messages Log\n")
150
145
  f.write(f"Session ID: {self.session_id}\n")
151
- f.write(
152
- f"Session started: {datetime.now().strftime('%Y-%m-%d %H:%M:%S')}\n"
153
- )
146
+ f.write(f"Session started: {datetime.now().strftime('%Y-%m-%d %H:%M:%S')}\n")
154
147
  f.write("=" * 80 + "\n\n")
155
148
  except Exception as e:
156
149
  print(f"Warning: Failed to initialize system log: {e}")
@@ -161,17 +154,13 @@ class MassLogManager:
161
154
  if self.non_blocking:
162
155
  return
163
156
 
164
- log_formatter = logging.Formatter(
165
- "%(asctime)s - %(name)s - %(levelname)s - %(message)s"
166
- )
157
+ log_formatter = logging.Formatter("%(asctime)s - %(name)s - %(levelname)s - %(message)s")
167
158
 
168
159
  # Ensure log directory exists before creating file handler
169
160
  try:
170
161
  self.session_dir.mkdir(parents=True, exist_ok=True)
171
162
  except Exception as e:
172
- print(
173
- f"Warning: Failed to create session directory {self.session_dir}, skipping file logging: {e}"
174
- )
163
+ print(f"Warning: Failed to create session directory {self.session_dir}, skipping file logging: {e}")
175
164
  return
176
165
 
177
166
  # Create console log file handler
@@ -250,31 +239,21 @@ class MassLogManager:
250
239
  f.write(f"📝 MASSGEN AGENT {agent_id} - ANSWER HISTORY\n")
251
240
  f.write("=" * 80 + "\n")
252
241
  f.write(f"🆔 Session: {self.session_id}\n")
253
- f.write(
254
- f"📅 Generated: {datetime.now().strftime('%Y-%m-%d %H:%M:%S')}\n"
255
- )
242
+ f.write(f"📅 Generated: {datetime.now().strftime('%Y-%m-%d %H:%M:%S')}\n")
256
243
 
257
244
  if answer_records:
258
245
  # Calculate some summary statistics
259
246
  total_chars = sum(len(record.answer) for record in answer_records)
260
- avg_chars = (
261
- total_chars / len(answer_records) if answer_records else 0
262
- )
247
+ avg_chars = total_chars / len(answer_records) if answer_records else 0
263
248
  first_update = answer_records[0].timestamp if answer_records else 0
264
249
  last_update = answer_records[-1].timestamp if answer_records else 0
265
- duration = (
266
- last_update - first_update if len(answer_records) > 1 else 0
267
- )
250
+ duration = last_update - first_update if len(answer_records) > 1 else 0
268
251
 
269
252
  f.write(f"📊 Total Updates: {len(answer_records)}\n")
270
253
  f.write(f"📏 Total Characters: {total_chars:,}\n")
271
254
  f.write(f"📈 Average Length: {avg_chars:.0f} chars\n")
272
255
  if duration > 0:
273
- duration_str = (
274
- f"{duration/60:.1f} minutes"
275
- if duration > 60
276
- else f"{duration:.1f} seconds"
277
- )
256
+ duration_str = f"{duration/60:.1f} minutes" if duration > 60 else f"{duration:.1f} seconds"
278
257
  f.write(f"⏱️ Time Span: {duration_str}\n")
279
258
  else:
280
259
  f.write("❌ No answer records found for this agent.\n")
@@ -284,16 +263,8 @@ class MassLogManager:
284
263
  if answer_records:
285
264
  for i, record in enumerate(answer_records, 1):
286
265
  # Calculate time elapsed since session start
287
- elapsed = record.timestamp - (
288
- answer_records[0].timestamp
289
- if answer_records
290
- else record.timestamp
291
- )
292
- elapsed_str = (
293
- f"[+{elapsed/60:.1f}m]"
294
- if elapsed > 60
295
- else f"[+{elapsed:.1f}s]"
296
- )
266
+ elapsed = record.timestamp - (answer_records[0].timestamp if answer_records else record.timestamp)
267
+ elapsed_str = f"[+{elapsed/60:.1f}m]" if elapsed > 60 else f"[+{elapsed:.1f}s]"
297
268
 
298
269
  f.write(f"🔢 UPDATE #{i} {elapsed_str}\n")
299
270
  f.write(self._format_answer_record(record, agent_id))
@@ -316,48 +287,30 @@ class MassLogManager:
316
287
  f.write(f"🗳️ MASSGEN AGENT {agent_id} - VOTE HISTORY\n")
317
288
  f.write("=" * 80 + "\n")
318
289
  f.write(f"🆔 Session: {self.session_id}\n")
319
- f.write(
320
- f"📅 Generated: {datetime.now().strftime('%Y-%m-%d %H:%M:%S')}\n"
321
- )
290
+ f.write(f"📅 Generated: {datetime.now().strftime('%Y-%m-%d %H:%M:%S')}\n")
322
291
 
323
292
  if vote_records:
324
293
  # Calculate voting statistics
325
294
  vote_targets = {}
326
295
  total_reason_chars = 0
327
296
  for vote in vote_records:
328
- vote_targets[vote.target_id] = (
329
- vote_targets.get(vote.target_id, 0) + 1
330
- )
297
+ vote_targets[vote.target_id] = vote_targets.get(vote.target_id, 0) + 1
331
298
  total_reason_chars += len(vote.reason) if vote.reason else 0
332
299
 
333
- most_voted_target = (
334
- max(vote_targets.items(), key=lambda x: x[1])
335
- if vote_targets
336
- else None
337
- )
338
- avg_reason_length = (
339
- total_reason_chars / len(vote_records) if vote_records else 0
340
- )
300
+ most_voted_target = max(vote_targets.items(), key=lambda x: x[1]) if vote_targets else None
301
+ avg_reason_length = total_reason_chars / len(vote_records) if vote_records else 0
341
302
 
342
303
  first_vote = vote_records[0].timestamp if vote_records else 0
343
304
  last_vote = vote_records[-1].timestamp if vote_records else 0
344
- voting_duration = (
345
- last_vote - first_vote if len(vote_records) > 1 else 0
346
- )
305
+ voting_duration = last_vote - first_vote if len(vote_records) > 1 else 0
347
306
 
348
307
  f.write(f"📊 Total Votes Cast: {len(vote_records)}\n")
349
308
  f.write(f"🎯 Unique Targets: {len(vote_targets)}\n")
350
309
  if most_voted_target:
351
- f.write(
352
- f"👑 Most Voted For: Agent {most_voted_target[0]} ({most_voted_target[1]} votes)\n"
353
- )
310
+ f.write(f"👑 Most Voted For: Agent {most_voted_target[0]} ({most_voted_target[1]} votes)\n")
354
311
  f.write(f"📝 Avg Reason Length: {avg_reason_length:.0f} chars\n")
355
312
  if voting_duration > 0:
356
- duration_str = (
357
- f"{voting_duration/60:.1f} minutes"
358
- if voting_duration > 60
359
- else f"{voting_duration:.1f} seconds"
360
- )
313
+ duration_str = f"{voting_duration/60:.1f} minutes" if voting_duration > 60 else f"{voting_duration:.1f} seconds"
361
314
  f.write(f"⏱️ Voting Duration: {duration_str}\n")
362
315
  else:
363
316
  f.write("❌ No vote records found for this agent.\n")
@@ -367,16 +320,8 @@ class MassLogManager:
367
320
  if vote_records:
368
321
  for i, record in enumerate(vote_records, 1):
369
322
  # Calculate time elapsed since first vote
370
- elapsed = record.timestamp - (
371
- vote_records[0].timestamp
372
- if vote_records
373
- else record.timestamp
374
- )
375
- elapsed_str = (
376
- f"[+{elapsed/60:.1f}m]"
377
- if elapsed > 60
378
- else f"[+{elapsed:.1f}s]"
379
- )
323
+ elapsed = record.timestamp - (vote_records[0].timestamp if vote_records else record.timestamp)
324
+ elapsed_str = f"[+{elapsed/60:.1f}m]" if elapsed > 60 else f"[+{elapsed:.1f}s]"
380
325
 
381
326
  f.write(f"🗳️ VOTE #{i} {elapsed_str}\n")
382
327
  f.write(self._format_vote_record(record, agent_id))
@@ -422,9 +367,7 @@ class MassLogManager:
422
367
  # Write to file immediately
423
368
  self._write_log_entry(entry)
424
369
 
425
- def log_agent_answer_update(
426
- self, agent_id: int, answer: str, phase: str = "unknown", orchestrator=None
427
- ):
370
+ def log_agent_answer_update(self, agent_id: int, answer: str, phase: str = "unknown", orchestrator=None):
428
371
  """
429
372
  Log agent answer update with detailed information and immediately save to file.
430
373
 
@@ -446,9 +389,7 @@ class MassLogManager:
446
389
  agent_state = orchestrator.agent_states[agent_id]
447
390
  self._write_agent_answers(agent_id, agent_state.updated_answers)
448
391
 
449
- def log_agent_status_change(
450
- self, agent_id: int, old_status: str, new_status: str, phase: str = "unknown"
451
- ):
392
+ def log_agent_status_change(self, agent_id: int, old_status: str, new_status: str, phase: str = "unknown"):
452
393
  """
453
394
  Log agent status change.
454
395
 
@@ -487,9 +428,7 @@ class MassLogManager:
487
428
  agent_states[agent_id] = {
488
429
  "status": agent_state.status,
489
430
  "curr_answer": agent_state.curr_answer,
490
- "vote_target": (
491
- agent_state.curr_vote.target_id if agent_state.curr_vote else None
492
- ),
431
+ "vote_target": (agent_state.curr_vote.target_id if agent_state.curr_vote else None),
493
432
  "execution_time": agent_state.execution_time,
494
433
  "update_count": len(agent_state.updated_answers),
495
434
  "seen_updates_timestamps": agent_state.seen_updates_timestamps,
@@ -515,7 +454,7 @@ class MassLogManager:
515
454
  "voter_id": vote.voter_id,
516
455
  "target_id": vote.target_id,
517
456
  "timestamp": vote.timestamp,
518
- }
457
+ },
519
458
  )
520
459
 
521
460
  # Calculate voting status
@@ -526,9 +465,7 @@ class MassLogManager:
526
465
  "total_agents": len(orchestrator.agents),
527
466
  "consensus_reached": orchestrator.system_state.consensus_reached,
528
467
  "winning_agent_id": orchestrator.system_state.representative_agent_id,
529
- "votes_needed_for_consensus": max(
530
- 1, int(len(orchestrator.agents) * orchestrator.consensus_threshold)
531
- ),
468
+ "votes_needed_for_consensus": max(1, int(len(orchestrator.agents) * orchestrator.consensus_threshold)),
532
469
  }
533
470
 
534
471
  # Complete system state snapshot
@@ -538,11 +475,7 @@ class MassLogManager:
538
475
  "voting_records": vote_records,
539
476
  "voting_status": voting_status,
540
477
  "system_phase": phase,
541
- "system_runtime": (
542
- (time.time() - orchestrator.system_state.start_time)
543
- if orchestrator.system_state.start_time
544
- else 0
545
- ),
478
+ "system_runtime": ((time.time() - orchestrator.system_state.start_time) if orchestrator.system_state.start_time else 0),
546
479
  }
547
480
 
548
481
  # Log the system snapshot
@@ -645,9 +578,7 @@ class MassLogManager:
645
578
  for agent_id in vote_distribution.keys():
646
579
  self._write_agent_display_log(agent_id, consensus_entry)
647
580
 
648
- def log_phase_transition(
649
- self, old_phase: str, new_phase: str, additional_data: Dict[str, Any] = None
650
- ):
581
+ def log_phase_transition(self, old_phase: str, new_phase: str, additional_data: Dict[str, Any] = None):
651
582
  """
652
583
  Log system phase transitions.
653
584
 
@@ -686,11 +617,7 @@ class MassLogManager:
686
617
 
687
618
  data = {
688
619
  "notification_type": notification_type,
689
- "content_preview": (
690
- content_preview[:200] + "..."
691
- if len(content_preview) > 200
692
- else content_preview
693
- ),
620
+ "content_preview": (content_preview[:200] + "..." if len(content_preview) > 200 else content_preview),
694
621
  "content_length": len(content_preview),
695
622
  "total_notifications_sent": self.event_counters["notifications_sent"],
696
623
  }
@@ -794,16 +721,12 @@ class MassLogManager:
794
721
  with open(agent_log_file, "w", encoding="utf-8") as f:
795
722
  f.write(f"MassGen Agent {agent_id} Display Log\n")
796
723
  f.write(f"Session: {self.session_id}\n")
797
- f.write(
798
- f"Started: {datetime.now().strftime('%Y-%m-%d %H:%M:%S')}\n"
799
- )
724
+ f.write(f"Started: {datetime.now().strftime('%Y-%m-%d %H:%M:%S')}\n")
800
725
  f.write("=" * 80 + "\n\n")
801
726
 
802
727
  # Write event entry
803
728
  with open(agent_log_file, "a", encoding="utf-8") as f:
804
- timestamp_str = self._format_timestamp(
805
- data.get("timestamp", time.time())
806
- )
729
+ timestamp_str = self._format_timestamp(data.get("timestamp", time.time()))
807
730
  f.write(f"[{timestamp_str}] {data.get('event', 'unknown_event')}\n")
808
731
 
809
732
  # Write event details
@@ -842,9 +765,7 @@ class MassLogManager:
842
765
 
843
766
  for entry in self.log_entries:
844
767
  # Count events
845
- event_counts[entry.event_type] = (
846
- event_counts.get(entry.event_type, 0) + 1
847
- )
768
+ event_counts[entry.event_type] = event_counts.get(entry.event_type, 0) + 1
848
769
 
849
770
  # Count agent activities
850
771
  if entry.agent_id is not None:
@@ -856,7 +777,7 @@ class MassLogManager:
856
777
  "timestamp": entry.timestamp,
857
778
  "event_type": entry.event_type,
858
779
  "phase": entry.phase,
859
- }
780
+ },
860
781
  )
861
782
 
862
783
  return {
@@ -930,8 +851,7 @@ class MassLogManager:
930
851
  "event_counters": self.event_counters.copy(),
931
852
  "agent_event_counts": agent_event_counts,
932
853
  "total_agents": len(self.agent_logs),
933
- "session_duration": time.time()
934
- - (self.log_entries[0].timestamp if self.log_entries else time.time()),
854
+ "session_duration": time.time() - (self.log_entries[0].timestamp if self.log_entries else time.time()),
935
855
  }
936
856
 
937
857
 
@@ -939,9 +859,7 @@ class MassLogManager:
939
859
  _log_manager: Optional[MassLogManager] = None
940
860
 
941
861
 
942
- def initialize_logging(
943
- log_dir: str = "logs", session_id: Optional[str] = None, non_blocking: bool = False
944
- ) -> MassLogManager:
862
+ def initialize_logging(log_dir: str = "logs", session_id: Optional[str] = None, non_blocking: bool = False) -> MassLogManager:
945
863
  """Initialize the global logging system."""
946
864
  global _log_manager
947
865
 
@@ -952,9 +870,7 @@ def initialize_logging(
952
870
  "yes",
953
871
  )
954
872
  if env_non_blocking:
955
- print(
956
- "🔧 MassGen_NON_BLOCKING_LOGGING environment variable detected - enabling non-blocking mode"
957
- )
873
+ print("🔧 MassGen_NON_BLOCKING_LOGGING environment variable detected - enabling non-blocking mode")
958
874
  non_blocking = True
959
875
 
960
876
  _log_manager = MassLogManager(log_dir, session_id, non_blocking)
massgen/v1/main.py CHANGED
@@ -1,4 +1,5 @@
1
1
  #!/usr/bin/env python3
2
+ # -*- coding: utf-8 -*-
2
3
  """
3
4
  MassGen (Multi-Agent Scaling System) - Programmatic Interface
4
5
 
@@ -22,28 +23,25 @@ Programmatic usage examples:
22
23
  result = system.run("Complex question here")
23
24
  """
24
25
 
25
- import sys
26
- import os
26
+ import json
27
27
  import logging
28
+ import os
29
+ import sys
28
30
  import time
29
- import json
30
- from typing import List, Dict, Any, Optional, Union
31
- from pathlib import Path
32
-
33
- # Add current directory to path for imports
34
- sys.path.append(os.path.dirname(__file__))
31
+ from typing import Any, Dict, List
35
32
 
36
- from .types import TaskInput, MassConfig, ModelConfig, AgentConfig
33
+ from .agents import create_agent
37
34
  from .config import create_config_from_models
35
+ from .logging import MassLogManager
38
36
  from .orchestrator import MassOrchestrator
39
- from .agents import create_agent
40
37
  from .streaming_display import create_streaming_display
41
- from .logging import MassLogManager
38
+ from .types import MassConfig, TaskInput
39
+
40
+ # Add current directory to path for imports
41
+ sys.path.append(os.path.dirname(__file__))
42
42
 
43
43
  # Initialize logging
44
- logging.basicConfig(
45
- level=logging.INFO, format="%(asctime)s - %(levelname)s - %(message)s"
46
- )
44
+ logging.basicConfig(level=logging.INFO, format="%(asctime)s - %(levelname)s - %(message)s")
47
45
  logger = logging.getLogger(__name__)
48
46
 
49
47
 
@@ -85,15 +83,13 @@ def _run_single_agent_simple(question: str, config: MassConfig) -> Dict[str, Any
85
83
  messages = [
86
84
  {
87
85
  "role": "system",
88
- "content": f"You are an expert agent equipped with tools to solve complex tasks. Please provide a comprehensive answer to the user's question.",
86
+ "content": "You are an expert agent equipped with tools to solve complex tasks. Please provide a comprehensive answer to the user's question.",
89
87
  },
90
88
  {"role": "user", "content": question},
91
89
  ]
92
90
 
93
91
  # Get available tools from agent configuration
94
- tools = (
95
- agent_config.model_config.tools if agent_config.model_config.tools else []
96
- )
92
+ tools = agent_config.model_config.tools if agent_config.model_config.tools else []
97
93
 
98
94
  # Call process_message directly
99
95
  result = agent.process_message(messages=messages, tools=tools)
@@ -111,9 +107,7 @@ def _run_single_agent_simple(question: str, config: MassConfig) -> Dict[str, Any
111
107
  "total_agents": 1,
112
108
  "failed_agents": 0,
113
109
  "total_votes": 1,
114
- "final_vote_distribution": {
115
- agent_config.agent_id: 1
116
- }, # Single agent votes for itself
110
+ "final_vote_distribution": {agent_config.agent_id: 1}, # Single agent votes for itself
117
111
  },
118
112
  "model_used": agent_config.model_config.model,
119
113
  "citations": result.citations if hasattr(result, "citations") else [],
@@ -162,9 +156,7 @@ def _run_single_agent_simple(question: str, config: MassConfig) -> Dict[str, Any
162
156
  try:
163
157
  result_file = log_manager.session_dir / "result.json"
164
158
  with open(result_file, "w", encoding="utf-8") as f:
165
- json.dump(
166
- error_response, f, indent=2, ensure_ascii=False, default=str
167
- )
159
+ json.dump(error_response, f, indent=2, ensure_ascii=False, default=str)
168
160
  logger.info(f"💾 Single agent error result saved to {result_file}")
169
161
  except Exception as e:
170
162
  logger.warning(f"⚠️ Failed to save result.json: {e}")
@@ -219,9 +211,7 @@ def run_mass_with_config(question: str, config: MassConfig) -> Dict[str, Any]:
219
211
  max_lines=config.streaming_display.max_lines,
220
212
  save_logs=config.streaming_display.save_logs,
221
213
  stream_callback=config.streaming_display.stream_callback,
222
- answers_dir=(
223
- str(log_manager.answers_dir) if not log_manager.non_blocking else None
224
- ),
214
+ answers_dir=(str(log_manager.answers_dir) if not log_manager.non_blocking else None),
225
215
  )
226
216
 
227
217
  # Create orchestrator with full configuration
@@ -353,11 +343,7 @@ def run_mass_agents(
353
343
  orchestrator_config={
354
344
  "max_duration": max_duration,
355
345
  "consensus_threshold": consensus_threshold,
356
- **{
357
- k: v
358
- for k, v in kwargs.items()
359
- if k in ["max_debate_rounds", "status_check_interval"]
360
- },
346
+ **{k: v for k, v in kwargs.items() if k in ["max_debate_rounds", "status_check_interval"]},
361
347
  },
362
348
  streaming_config={
363
349
  "display_enabled": streaming_display,