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
@@ -1,3 +1,4 @@
1
+ # -*- coding: utf-8 -*-
1
2
  """
2
3
  Simple Display for MassGen Coordination
3
4
 
@@ -5,6 +6,7 @@ Basic text output display for minimal use cases and debugging.
5
6
  """
6
7
 
7
8
  from typing import Optional
9
+
8
10
  from .base_display import BaseDisplay
9
11
 
10
12
 
@@ -25,9 +27,7 @@ class SimpleDisplay(BaseDisplay):
25
27
  print(f"👥 Agents: {', '.join(self.agent_ids)}")
26
28
  print("=" * 50)
27
29
 
28
- def update_agent_content(
29
- self, agent_id: str, content: str, content_type: str = "thinking"
30
- ):
30
+ def update_agent_content(self, agent_id: str, content: str, content_type: str = "thinking"):
31
31
  """Update content for a specific agent."""
32
32
  if agent_id not in self.agent_ids:
33
33
  return
@@ -79,10 +79,15 @@ class SimpleDisplay(BaseDisplay):
79
79
  if self.show_events:
80
80
  print(f"🎭 {event}")
81
81
 
82
- def show_final_answer(self, answer: str):
82
+ def show_final_answer(self, answer: str, vote_results=None, selected_agent=None):
83
83
  """Display the final coordinated answer."""
84
84
  print("\n" + "=" * 50)
85
85
  print(f"🎯 FINAL ANSWER: {answer}")
86
+ if selected_agent:
87
+ print(f"✅ Selected by: {selected_agent}")
88
+ if vote_results:
89
+ vote_summary = ", ".join([f"{agent}: {votes}" for agent, votes in vote_results.items()])
90
+ print(f"🗳️ Vote results: {vote_summary}")
86
91
  print("=" * 50)
87
92
 
88
93
  def cleanup(self):
@@ -1,3 +1,4 @@
1
+ # -*- coding: utf-8 -*-
1
2
  """
2
3
  Terminal Display for MassGen Coordination
3
4
 
@@ -6,6 +7,7 @@ Rich terminal interface with live updates, agent columns, and coordination event
6
7
 
7
8
  import os
8
9
  from typing import List, Optional
10
+
9
11
  from .base_display import BaseDisplay
10
12
 
11
13
 
@@ -36,9 +38,7 @@ class TerminalDisplay(BaseDisplay):
36
38
  self.col_width = (self.terminal_width - 3) // 2
37
39
  self.separators = " │ "
38
40
  else:
39
- self.col_width = (
40
- self.terminal_width - (self.num_agents - 1) * 3
41
- ) // self.num_agents
41
+ self.col_width = (self.terminal_width - (self.num_agents - 1) * 3) // self.num_agents
42
42
  self.separators = " │ "
43
43
 
44
44
  def _get_terminal_width(self) -> int:
@@ -57,7 +57,7 @@ class TerminalDisplay(BaseDisplay):
57
57
 
58
58
  try:
59
59
  os.system("clear" if os.name == "posix" else "cls")
60
- except:
60
+ except Exception:
61
61
  print("\033[2J\033[H", end="")
62
62
 
63
63
  title = f"🚀 {'Multi' if self.num_agents > 2 else 'Two' if self.num_agents == 2 else 'Single'}-Agent Coordination Dashboard"
@@ -73,20 +73,12 @@ class TerminalDisplay(BaseDisplay):
73
73
  for agent_id in self.agent_ids:
74
74
  # Try to get backend info from orchestrator if available
75
75
  backend_name = "Unknown"
76
- if (
77
- hasattr(self, "orchestrator")
78
- and self.orchestrator
79
- and hasattr(self.orchestrator, "agents")
80
- ):
76
+ if hasattr(self, "orchestrator") and self.orchestrator and hasattr(self.orchestrator, "agents"):
81
77
  agent = self.orchestrator.agents.get(agent_id)
82
- if (
83
- agent
84
- and hasattr(agent, "backend")
85
- and hasattr(agent.backend, "get_provider_name")
86
- ):
78
+ if agent and hasattr(agent, "backend") and hasattr(agent.backend, "get_provider_name"):
87
79
  try:
88
80
  backend_name = agent.backend.get_provider_name()
89
- except:
81
+ except Exception:
90
82
  backend_name = "Unknown"
91
83
 
92
84
  # Generic header format for any agent
@@ -103,9 +95,7 @@ class TerminalDisplay(BaseDisplay):
103
95
  print("=" * self.terminal_width)
104
96
  print()
105
97
 
106
- def update_agent_content(
107
- self, agent_id: str, content: str, content_type: str = "thinking"
108
- ):
98
+ def update_agent_content(self, agent_id: str, content: str, content_type: str = "thinking"):
109
99
  """Update content for a specific agent."""
110
100
  if agent_id not in self.agent_ids:
111
101
  return
@@ -142,10 +132,7 @@ class TerminalDisplay(BaseDisplay):
142
132
  should_refresh = True # Always refresh for presentations
143
133
  else:
144
134
  # Thinking content - smart formatting based on content type
145
- if (
146
- self.agent_outputs[agent_id]
147
- and self.agent_outputs[agent_id][-1] == "⚡ Working..."
148
- ):
135
+ if self.agent_outputs[agent_id] and self.agent_outputs[agent_id][-1] == "⚡ Working...":
149
136
  # Replace "Working..." with actual thinking
150
137
  self.agent_outputs[agent_id][-1] = clean_content
151
138
  should_refresh = True # Refresh when replacing "Working..."
@@ -235,9 +222,7 @@ class TerminalDisplay(BaseDisplay):
235
222
  if old_status != "working" and status == "working":
236
223
  agent_prefix = f"[{agent_id}] " if self.num_agents > 1 else ""
237
224
  print(f"\n{agent_prefix}⚡ Working...")
238
- if not self.agent_outputs[agent_id] or not self.agent_outputs[agent_id][
239
- -1
240
- ].startswith("⚡"):
225
+ if not self.agent_outputs[agent_id] or not self.agent_outputs[agent_id][-1].startswith("⚡"):
241
226
  self.agent_outputs[agent_id].append("⚡ Working...")
242
227
 
243
228
  # Show status update in footer
@@ -248,17 +233,21 @@ class TerminalDisplay(BaseDisplay):
248
233
  self.orchestrator_events.append(event)
249
234
  self._refresh_display()
250
235
 
251
- def show_final_answer(self, answer: str):
236
+ def show_final_answer(self, answer: str, vote_results=None, selected_agent=None):
252
237
  """Display the final coordinated answer prominently."""
253
- print(f"\n🎯 FINAL COORDINATED ANSWER:")
238
+ print("\n🎯 FINAL COORDINATED ANSWER:")
254
239
  print("=" * 60)
255
240
  print(f"📋 {answer}")
241
+ if selected_agent:
242
+ print(f"✅ Selected by: {selected_agent}")
243
+ if vote_results:
244
+ vote_summary = ", ".join([f"{agent}: {votes}" for agent, votes in vote_results.items()])
245
+ print(f"🗳️ Vote results: {vote_summary}")
256
246
  print("=" * 60)
257
247
 
258
248
  def cleanup(self):
259
249
  """Clean up display resources."""
260
250
  # No special cleanup needed for terminal display
261
- pass
262
251
 
263
252
  def _refresh_display(self):
264
253
  """Refresh the entire display with proper columns."""
@@ -273,20 +262,12 @@ class TerminalDisplay(BaseDisplay):
273
262
  print("\033[7;1H\033[0J", end="") # Move to line 7 and clear down
274
263
 
275
264
  # Show agent outputs in columns with word wrapping
276
- max_lines = (
277
- max(len(self.agent_outputs[agent_id]) for agent_id in self.agent_ids)
278
- if self.agent_outputs
279
- else 0
280
- )
265
+ max_lines = max(len(self.agent_outputs[agent_id]) for agent_id in self.agent_ids) if self.agent_outputs else 0
281
266
 
282
267
  # For single agent, don't wrap - show full content
283
268
  if self.num_agents == 1:
284
269
  for i in range(max_lines):
285
- line = (
286
- self.agent_outputs[self.agent_ids[0]][i]
287
- if i < len(self.agent_outputs[self.agent_ids[0]])
288
- else ""
289
- )
270
+ line = self.agent_outputs[self.agent_ids[0]][i] if i < len(self.agent_outputs[self.agent_ids[0]]) else ""
290
271
  print(line)
291
272
  else:
292
273
  # For multiple agents, wrap long lines to fit columns
@@ -299,18 +280,14 @@ class TerminalDisplay(BaseDisplay):
299
280
  words = line.split(" ")
300
281
  current_line = ""
301
282
  for word in words:
302
- test_line = (
303
- current_line + (" " if current_line else "") + word
304
- )
283
+ test_line = current_line + (" " if current_line else "") + word
305
284
  if len(test_line) > self.col_width - 2:
306
285
  if current_line:
307
286
  wrapped_outputs[agent_id].append(current_line)
308
287
  current_line = word
309
288
  else:
310
289
  # Single word longer than column width - truncate gracefully
311
- wrapped_outputs[agent_id].append(
312
- word[: self.col_width - 2] + "…"
313
- )
290
+ wrapped_outputs[agent_id].append(word[: self.col_width - 2] + "…")
314
291
  current_line = ""
315
292
  else:
316
293
  current_line = test_line
@@ -320,19 +297,11 @@ class TerminalDisplay(BaseDisplay):
320
297
  wrapped_outputs[agent_id].append(line)
321
298
 
322
299
  # Display wrapped content
323
- max_wrapped_lines = (
324
- max(len(wrapped_outputs[agent_id]) for agent_id in self.agent_ids)
325
- if wrapped_outputs
326
- else 0
327
- )
300
+ max_wrapped_lines = max(len(wrapped_outputs[agent_id]) for agent_id in self.agent_ids) if wrapped_outputs else 0
328
301
  for i in range(max_wrapped_lines):
329
302
  output_lines = []
330
303
  for agent_id in self.agent_ids:
331
- line = (
332
- wrapped_outputs[agent_id][i]
333
- if i < len(wrapped_outputs[agent_id])
334
- else ""
335
- )
304
+ line = wrapped_outputs[agent_id][i] if i < len(wrapped_outputs[agent_id]) else ""
336
305
  output_lines.append(f"{line:<{self.col_width}}")
337
306
  print(self.separators.join(output_lines))
338
307
 
@@ -344,25 +313,15 @@ class TerminalDisplay(BaseDisplay):
344
313
  for agent_id in self.agent_ids:
345
314
  # Get backend info same as in header
346
315
  backend_name = "Unknown"
347
- if (
348
- hasattr(self, "orchestrator")
349
- and self.orchestrator
350
- and hasattr(self.orchestrator, "agents")
351
- ):
316
+ if hasattr(self, "orchestrator") and self.orchestrator and hasattr(self.orchestrator, "agents"):
352
317
  agent = self.orchestrator.agents.get(agent_id)
353
- if (
354
- agent
355
- and hasattr(agent, "backend")
356
- and hasattr(agent.backend, "get_provider_name")
357
- ):
318
+ if agent and hasattr(agent, "backend") and hasattr(agent.backend, "get_provider_name"):
358
319
  try:
359
320
  backend_name = agent.backend.get_provider_name()
360
- except:
321
+ except Exception:
361
322
  backend_name = "Unknown"
362
323
 
363
- status_text = (
364
- f"{agent_id.upper()} ({backend_name}): {self.agent_status[agent_id]}"
365
- )
324
+ status_text = f"{agent_id.upper()} ({backend_name}): {self.agent_status[agent_id]}"
366
325
  status_lines.append(f"{status_text:^{self.col_width}}")
367
326
 
368
327
  if self.num_agents == 1: