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.
- massgen/__init__.py +142 -8
- massgen/adapters/__init__.py +29 -0
- massgen/adapters/ag2_adapter.py +483 -0
- massgen/adapters/base.py +183 -0
- massgen/adapters/tests/__init__.py +0 -0
- massgen/adapters/tests/test_ag2_adapter.py +439 -0
- massgen/adapters/tests/test_agent_adapter.py +128 -0
- massgen/adapters/utils/__init__.py +2 -0
- massgen/adapters/utils/ag2_utils.py +236 -0
- massgen/adapters/utils/tests/__init__.py +0 -0
- massgen/adapters/utils/tests/test_ag2_utils.py +138 -0
- massgen/agent_config.py +329 -55
- massgen/api_params_handler/__init__.py +10 -0
- massgen/api_params_handler/_api_params_handler_base.py +99 -0
- massgen/api_params_handler/_chat_completions_api_params_handler.py +176 -0
- massgen/api_params_handler/_claude_api_params_handler.py +113 -0
- massgen/api_params_handler/_response_api_params_handler.py +130 -0
- massgen/backend/__init__.py +39 -4
- massgen/backend/azure_openai.py +385 -0
- massgen/backend/base.py +341 -69
- massgen/backend/base_with_mcp.py +1102 -0
- massgen/backend/capabilities.py +386 -0
- massgen/backend/chat_completions.py +577 -130
- massgen/backend/claude.py +1033 -537
- massgen/backend/claude_code.py +1203 -0
- massgen/backend/cli_base.py +209 -0
- massgen/backend/docs/BACKEND_ARCHITECTURE.md +126 -0
- massgen/backend/{CLAUDE_API_RESEARCH.md → docs/CLAUDE_API_RESEARCH.md} +18 -18
- massgen/backend/{GEMINI_API_DOCUMENTATION.md → docs/GEMINI_API_DOCUMENTATION.md} +9 -9
- massgen/backend/docs/Gemini MCP Integration Analysis.md +1050 -0
- massgen/backend/docs/MCP_IMPLEMENTATION_CLAUDE_BACKEND.md +177 -0
- massgen/backend/docs/MCP_INTEGRATION_RESPONSE_BACKEND.md +352 -0
- massgen/backend/docs/OPENAI_GPT5_MODELS.md +211 -0
- massgen/backend/{OPENAI_RESPONSES_API_FORMAT.md → docs/OPENAI_RESPONSE_API_TOOL_CALLS.md} +3 -3
- massgen/backend/docs/OPENAI_response_streaming.md +20654 -0
- massgen/backend/docs/inference_backend.md +257 -0
- massgen/backend/docs/permissions_and_context_files.md +1085 -0
- massgen/backend/external.py +126 -0
- massgen/backend/gemini.py +1850 -241
- massgen/backend/grok.py +40 -156
- massgen/backend/inference.py +156 -0
- massgen/backend/lmstudio.py +171 -0
- massgen/backend/response.py +1095 -322
- massgen/chat_agent.py +131 -113
- massgen/cli.py +1560 -275
- massgen/config_builder.py +2396 -0
- massgen/configs/BACKEND_CONFIGURATION.md +458 -0
- massgen/configs/README.md +559 -216
- massgen/configs/ag2/ag2_case_study.yaml +27 -0
- massgen/configs/ag2/ag2_coder.yaml +34 -0
- massgen/configs/ag2/ag2_coder_case_study.yaml +36 -0
- massgen/configs/ag2/ag2_gemini.yaml +27 -0
- massgen/configs/ag2/ag2_groupchat.yaml +108 -0
- massgen/configs/ag2/ag2_groupchat_gpt.yaml +118 -0
- massgen/configs/ag2/ag2_single_agent.yaml +21 -0
- massgen/configs/basic/multi/fast_timeout_example.yaml +37 -0
- massgen/configs/basic/multi/gemini_4o_claude.yaml +31 -0
- massgen/configs/basic/multi/gemini_gpt5nano_claude.yaml +36 -0
- massgen/configs/{gemini_4o_claude.yaml → basic/multi/geminicode_4o_claude.yaml} +3 -3
- massgen/configs/basic/multi/geminicode_gpt5nano_claude.yaml +36 -0
- massgen/configs/basic/multi/glm_gemini_claude.yaml +25 -0
- massgen/configs/basic/multi/gpt4o_audio_generation.yaml +30 -0
- massgen/configs/basic/multi/gpt4o_image_generation.yaml +31 -0
- massgen/configs/basic/multi/gpt5nano_glm_qwen.yaml +26 -0
- massgen/configs/basic/multi/gpt5nano_image_understanding.yaml +26 -0
- massgen/configs/{three_agents_default.yaml → basic/multi/three_agents_default.yaml} +8 -4
- massgen/configs/basic/multi/three_agents_opensource.yaml +27 -0
- massgen/configs/basic/multi/three_agents_vllm.yaml +20 -0
- massgen/configs/basic/multi/two_agents_gemini.yaml +19 -0
- massgen/configs/{two_agents.yaml → basic/multi/two_agents_gpt5.yaml} +14 -6
- massgen/configs/basic/multi/two_agents_opensource_lmstudio.yaml +31 -0
- massgen/configs/basic/multi/two_qwen_vllm_sglang.yaml +28 -0
- massgen/configs/{single_agent.yaml → basic/single/single_agent.yaml} +1 -1
- massgen/configs/{single_flash2.5.yaml → basic/single/single_flash2.5.yaml} +1 -2
- massgen/configs/basic/single/single_gemini2.5pro.yaml +16 -0
- massgen/configs/basic/single/single_gpt4o_audio_generation.yaml +22 -0
- massgen/configs/basic/single/single_gpt4o_image_generation.yaml +22 -0
- massgen/configs/basic/single/single_gpt4o_video_generation.yaml +24 -0
- massgen/configs/basic/single/single_gpt5nano.yaml +20 -0
- massgen/configs/basic/single/single_gpt5nano_file_search.yaml +18 -0
- massgen/configs/basic/single/single_gpt5nano_image_understanding.yaml +17 -0
- massgen/configs/basic/single/single_gptoss120b.yaml +15 -0
- massgen/configs/basic/single/single_openrouter_audio_understanding.yaml +15 -0
- massgen/configs/basic/single/single_qwen_video_understanding.yaml +15 -0
- massgen/configs/debug/code_execution/command_filtering_blacklist.yaml +29 -0
- massgen/configs/debug/code_execution/command_filtering_whitelist.yaml +28 -0
- massgen/configs/debug/code_execution/docker_verification.yaml +29 -0
- massgen/configs/debug/skip_coordination_test.yaml +27 -0
- massgen/configs/debug/test_sdk_migration.yaml +17 -0
- massgen/configs/docs/DISCORD_MCP_SETUP.md +208 -0
- massgen/configs/docs/TWITTER_MCP_ENESCINAR_SETUP.md +82 -0
- massgen/configs/providers/azure/azure_openai_multi.yaml +21 -0
- massgen/configs/providers/azure/azure_openai_single.yaml +19 -0
- massgen/configs/providers/claude/claude.yaml +14 -0
- massgen/configs/providers/gemini/gemini_gpt5nano.yaml +28 -0
- massgen/configs/providers/local/lmstudio.yaml +11 -0
- massgen/configs/providers/openai/gpt5.yaml +46 -0
- massgen/configs/providers/openai/gpt5_nano.yaml +46 -0
- massgen/configs/providers/others/grok_single_agent.yaml +19 -0
- massgen/configs/providers/others/zai_coding_team.yaml +108 -0
- massgen/configs/providers/others/zai_glm45.yaml +12 -0
- massgen/configs/{creative_team.yaml → teams/creative/creative_team.yaml} +16 -6
- massgen/configs/{travel_planning.yaml → teams/creative/travel_planning.yaml} +16 -6
- massgen/configs/{news_analysis.yaml → teams/research/news_analysis.yaml} +16 -6
- massgen/configs/{research_team.yaml → teams/research/research_team.yaml} +15 -7
- massgen/configs/{technical_analysis.yaml → teams/research/technical_analysis.yaml} +16 -6
- massgen/configs/tools/code-execution/basic_command_execution.yaml +25 -0
- massgen/configs/tools/code-execution/code_execution_use_case_simple.yaml +41 -0
- massgen/configs/tools/code-execution/docker_claude_code.yaml +32 -0
- massgen/configs/tools/code-execution/docker_multi_agent.yaml +32 -0
- massgen/configs/tools/code-execution/docker_simple.yaml +29 -0
- massgen/configs/tools/code-execution/docker_with_resource_limits.yaml +32 -0
- massgen/configs/tools/code-execution/multi_agent_playwright_automation.yaml +57 -0
- massgen/configs/tools/filesystem/cc_gpt5_gemini_filesystem.yaml +34 -0
- massgen/configs/tools/filesystem/claude_code_context_sharing.yaml +68 -0
- massgen/configs/tools/filesystem/claude_code_flash2.5.yaml +43 -0
- massgen/configs/tools/filesystem/claude_code_flash2.5_gptoss.yaml +49 -0
- massgen/configs/tools/filesystem/claude_code_gpt5nano.yaml +31 -0
- massgen/configs/tools/filesystem/claude_code_single.yaml +40 -0
- massgen/configs/tools/filesystem/fs_permissions_test.yaml +87 -0
- massgen/configs/tools/filesystem/gemini_gemini_workspace_cleanup.yaml +54 -0
- massgen/configs/tools/filesystem/gemini_gpt5_filesystem_casestudy.yaml +30 -0
- massgen/configs/tools/filesystem/gemini_gpt5nano_file_context_path.yaml +43 -0
- massgen/configs/tools/filesystem/gemini_gpt5nano_protected_paths.yaml +45 -0
- massgen/configs/tools/filesystem/gpt5mini_cc_fs_context_path.yaml +31 -0
- massgen/configs/tools/filesystem/grok4_gpt5_gemini_filesystem.yaml +32 -0
- massgen/configs/tools/filesystem/multiturn/grok4_gpt5_claude_code_filesystem_multiturn.yaml +58 -0
- massgen/configs/tools/filesystem/multiturn/grok4_gpt5_gemini_filesystem_multiturn.yaml +58 -0
- massgen/configs/tools/filesystem/multiturn/two_claude_code_filesystem_multiturn.yaml +47 -0
- massgen/configs/tools/filesystem/multiturn/two_gemini_flash_filesystem_multiturn.yaml +48 -0
- massgen/configs/tools/mcp/claude_code_discord_mcp_example.yaml +27 -0
- massgen/configs/tools/mcp/claude_code_simple_mcp.yaml +35 -0
- massgen/configs/tools/mcp/claude_code_twitter_mcp_example.yaml +32 -0
- massgen/configs/tools/mcp/claude_mcp_example.yaml +24 -0
- massgen/configs/tools/mcp/claude_mcp_test.yaml +27 -0
- massgen/configs/tools/mcp/five_agents_travel_mcp_test.yaml +157 -0
- massgen/configs/tools/mcp/five_agents_weather_mcp_test.yaml +103 -0
- massgen/configs/tools/mcp/gemini_mcp_example.yaml +24 -0
- massgen/configs/tools/mcp/gemini_mcp_filesystem_test.yaml +23 -0
- massgen/configs/tools/mcp/gemini_mcp_filesystem_test_sharing.yaml +23 -0
- massgen/configs/tools/mcp/gemini_mcp_filesystem_test_single_agent.yaml +17 -0
- massgen/configs/tools/mcp/gemini_mcp_filesystem_test_with_claude_code.yaml +24 -0
- massgen/configs/tools/mcp/gemini_mcp_test.yaml +27 -0
- massgen/configs/tools/mcp/gemini_notion_mcp.yaml +52 -0
- massgen/configs/tools/mcp/gpt5_nano_mcp_example.yaml +24 -0
- massgen/configs/tools/mcp/gpt5_nano_mcp_test.yaml +27 -0
- massgen/configs/tools/mcp/gpt5mini_claude_code_discord_mcp_example.yaml +38 -0
- massgen/configs/tools/mcp/gpt_oss_mcp_example.yaml +25 -0
- massgen/configs/tools/mcp/gpt_oss_mcp_test.yaml +28 -0
- massgen/configs/tools/mcp/grok3_mini_mcp_example.yaml +24 -0
- massgen/configs/tools/mcp/grok3_mini_mcp_test.yaml +27 -0
- massgen/configs/tools/mcp/multimcp_gemini.yaml +111 -0
- massgen/configs/tools/mcp/qwen_api_mcp_example.yaml +25 -0
- massgen/configs/tools/mcp/qwen_api_mcp_test.yaml +28 -0
- massgen/configs/tools/mcp/qwen_local_mcp_example.yaml +24 -0
- massgen/configs/tools/mcp/qwen_local_mcp_test.yaml +27 -0
- massgen/configs/tools/planning/five_agents_discord_mcp_planning_mode.yaml +140 -0
- massgen/configs/tools/planning/five_agents_filesystem_mcp_planning_mode.yaml +151 -0
- massgen/configs/tools/planning/five_agents_notion_mcp_planning_mode.yaml +151 -0
- massgen/configs/tools/planning/five_agents_twitter_mcp_planning_mode.yaml +155 -0
- massgen/configs/tools/planning/gpt5_mini_case_study_mcp_planning_mode.yaml +73 -0
- massgen/configs/tools/web-search/claude_streamable_http_test.yaml +43 -0
- massgen/configs/tools/web-search/gemini_streamable_http_test.yaml +43 -0
- massgen/configs/tools/web-search/gpt5_mini_streamable_http_test.yaml +43 -0
- massgen/configs/tools/web-search/gpt_oss_streamable_http_test.yaml +44 -0
- massgen/configs/tools/web-search/grok3_mini_streamable_http_test.yaml +43 -0
- massgen/configs/tools/web-search/qwen_api_streamable_http_test.yaml +44 -0
- massgen/configs/tools/web-search/qwen_local_streamable_http_test.yaml +43 -0
- massgen/coordination_tracker.py +708 -0
- massgen/docker/README.md +462 -0
- massgen/filesystem_manager/__init__.py +21 -0
- massgen/filesystem_manager/_base.py +9 -0
- massgen/filesystem_manager/_code_execution_server.py +545 -0
- massgen/filesystem_manager/_docker_manager.py +477 -0
- massgen/filesystem_manager/_file_operation_tracker.py +248 -0
- massgen/filesystem_manager/_filesystem_manager.py +813 -0
- massgen/filesystem_manager/_path_permission_manager.py +1261 -0
- massgen/filesystem_manager/_workspace_tools_server.py +1815 -0
- massgen/formatter/__init__.py +10 -0
- massgen/formatter/_chat_completions_formatter.py +284 -0
- massgen/formatter/_claude_formatter.py +235 -0
- massgen/formatter/_formatter_base.py +156 -0
- massgen/formatter/_response_formatter.py +263 -0
- massgen/frontend/__init__.py +1 -2
- massgen/frontend/coordination_ui.py +471 -286
- massgen/frontend/displays/base_display.py +56 -11
- massgen/frontend/displays/create_coordination_table.py +1956 -0
- massgen/frontend/displays/rich_terminal_display.py +1259 -619
- massgen/frontend/displays/simple_display.py +9 -4
- massgen/frontend/displays/terminal_display.py +27 -68
- massgen/logger_config.py +681 -0
- massgen/mcp_tools/README.md +232 -0
- massgen/mcp_tools/__init__.py +105 -0
- massgen/mcp_tools/backend_utils.py +1035 -0
- massgen/mcp_tools/circuit_breaker.py +195 -0
- massgen/mcp_tools/client.py +894 -0
- massgen/mcp_tools/config_validator.py +138 -0
- massgen/mcp_tools/docs/circuit_breaker.md +646 -0
- massgen/mcp_tools/docs/client.md +950 -0
- massgen/mcp_tools/docs/config_validator.md +478 -0
- massgen/mcp_tools/docs/exceptions.md +1165 -0
- massgen/mcp_tools/docs/security.md +854 -0
- massgen/mcp_tools/exceptions.py +338 -0
- massgen/mcp_tools/hooks.py +212 -0
- massgen/mcp_tools/security.py +780 -0
- massgen/message_templates.py +342 -64
- massgen/orchestrator.py +1515 -241
- massgen/stream_chunk/__init__.py +35 -0
- massgen/stream_chunk/base.py +92 -0
- massgen/stream_chunk/multimodal.py +237 -0
- massgen/stream_chunk/text.py +162 -0
- massgen/tests/mcp_test_server.py +150 -0
- massgen/tests/multi_turn_conversation_design.md +0 -8
- massgen/tests/test_azure_openai_backend.py +156 -0
- massgen/tests/test_backend_capabilities.py +262 -0
- massgen/tests/test_backend_event_loop_all.py +179 -0
- massgen/tests/test_chat_completions_refactor.py +142 -0
- massgen/tests/test_claude_backend.py +15 -28
- massgen/tests/test_claude_code.py +268 -0
- massgen/tests/test_claude_code_context_sharing.py +233 -0
- massgen/tests/test_claude_code_orchestrator.py +175 -0
- massgen/tests/test_cli_backends.py +180 -0
- massgen/tests/test_code_execution.py +679 -0
- massgen/tests/test_external_agent_backend.py +134 -0
- massgen/tests/test_final_presentation_fallback.py +237 -0
- massgen/tests/test_gemini_planning_mode.py +351 -0
- massgen/tests/test_grok_backend.py +7 -10
- massgen/tests/test_http_mcp_server.py +42 -0
- massgen/tests/test_integration_simple.py +198 -0
- massgen/tests/test_mcp_blocking.py +125 -0
- massgen/tests/test_message_context_building.py +29 -47
- massgen/tests/test_orchestrator_final_presentation.py +48 -0
- massgen/tests/test_path_permission_manager.py +2087 -0
- massgen/tests/test_rich_terminal_display.py +14 -13
- massgen/tests/test_timeout.py +133 -0
- massgen/tests/test_v3_3agents.py +11 -12
- massgen/tests/test_v3_simple.py +8 -13
- massgen/tests/test_v3_three_agents.py +11 -18
- massgen/tests/test_v3_two_agents.py +8 -13
- massgen/token_manager/__init__.py +7 -0
- massgen/token_manager/token_manager.py +400 -0
- massgen/utils.py +52 -16
- massgen/v1/agent.py +45 -91
- massgen/v1/agents.py +18 -53
- massgen/v1/backends/gemini.py +50 -153
- massgen/v1/backends/grok.py +21 -54
- massgen/v1/backends/oai.py +39 -111
- massgen/v1/cli.py +36 -93
- massgen/v1/config.py +8 -12
- massgen/v1/logging.py +43 -127
- massgen/v1/main.py +18 -32
- massgen/v1/orchestrator.py +68 -209
- massgen/v1/streaming_display.py +62 -163
- massgen/v1/tools.py +8 -12
- massgen/v1/types.py +9 -23
- massgen/v1/utils.py +5 -23
- massgen-0.1.0.dist-info/METADATA +1245 -0
- massgen-0.1.0.dist-info/RECORD +273 -0
- massgen-0.1.0.dist-info/entry_points.txt +2 -0
- massgen/frontend/logging/__init__.py +0 -9
- massgen/frontend/logging/realtime_logger.py +0 -197
- massgen-0.0.3.dist-info/METADATA +0 -568
- massgen-0.0.3.dist-info/RECORD +0 -76
- massgen-0.0.3.dist-info/entry_points.txt +0 -2
- /massgen/backend/{Function calling openai responses.md → docs/Function calling openai responses.md} +0 -0
- {massgen-0.0.3.dist-info → massgen-0.1.0.dist-info}/WHEEL +0 -0
- {massgen-0.0.3.dist-info → massgen-0.1.0.dist-info}/licenses/LICENSE +0 -0
- {massgen-0.0.3.dist-info → massgen-0.1.0.dist-info}/top_level.txt +0 -0
massgen/v1/orchestrator.py
CHANGED
|
@@ -1,14 +1,15 @@
|
|
|
1
|
+
# -*- coding: utf-8 -*-
|
|
2
|
+
import json
|
|
1
3
|
import logging
|
|
2
4
|
import threading
|
|
3
5
|
import time
|
|
4
|
-
import json
|
|
5
6
|
from collections import Counter
|
|
6
|
-
from datetime import datetime
|
|
7
|
-
from typing import Any, Optional, Dict, List
|
|
8
7
|
from concurrent.futures import ThreadPoolExecutor
|
|
8
|
+
from datetime import datetime
|
|
9
|
+
from typing import Any, Dict, List, Optional
|
|
9
10
|
|
|
10
|
-
from .types import SystemState, AgentState, TaskInput, VoteRecord
|
|
11
11
|
from .logging import get_log_manager
|
|
12
|
+
from .types import AgentState, SystemState, TaskInput, VoteRecord
|
|
12
13
|
|
|
13
14
|
# Set up logging
|
|
14
15
|
logger = logging.getLogger(__name__)
|
|
@@ -84,9 +85,7 @@ class MassOrchestrator:
|
|
|
84
85
|
|
|
85
86
|
def _log_event(self, event_type: str, data: Dict[str, Any]):
|
|
86
87
|
"""Log an orchestrator event."""
|
|
87
|
-
self.communication_log.append(
|
|
88
|
-
{"timestamp": time.time(), "event_type": event_type, "data": data}
|
|
89
|
-
)
|
|
88
|
+
self.communication_log.append({"timestamp": time.time(), "event_type": event_type, "data": data})
|
|
90
89
|
|
|
91
90
|
def update_agent_answer(self, agent_id: int, answer: str):
|
|
92
91
|
"""
|
|
@@ -104,9 +103,7 @@ class MassOrchestrator:
|
|
|
104
103
|
self.agent_states[agent_id].add_update(answer)
|
|
105
104
|
|
|
106
105
|
preview = answer[:100] + "..." if len(answer) > 100 else answer
|
|
107
|
-
print(
|
|
108
|
-
f"📝 Agent {agent_id} answer updated ({old_answer_length} → {len(answer)} chars)"
|
|
109
|
-
)
|
|
106
|
+
print(f"📝 Agent {agent_id} answer updated ({old_answer_length} → {len(answer)} chars)")
|
|
110
107
|
print(f" 🔍 {preview}")
|
|
111
108
|
|
|
112
109
|
# Log to the comprehensive logging system
|
|
@@ -153,9 +150,7 @@ class MassOrchestrator:
|
|
|
153
150
|
"""Get current voting status and distribution."""
|
|
154
151
|
vote_counts = self._get_current_vote_counts()
|
|
155
152
|
total_agents = len(self.agents)
|
|
156
|
-
failed_agents = len(
|
|
157
|
-
[s for s in self.agent_states.values() if s.status == "failed"]
|
|
158
|
-
)
|
|
153
|
+
failed_agents = len([s for s in self.agent_states.values() if s.status == "failed"])
|
|
159
154
|
votable_agents = total_agents - failed_agents
|
|
160
155
|
voted_agents = self._get_current_voted_agents_count()
|
|
161
156
|
|
|
@@ -165,9 +160,7 @@ class MassOrchestrator:
|
|
|
165
160
|
"failed_agents": failed_agents,
|
|
166
161
|
"votable_agents": votable_agents,
|
|
167
162
|
"voted_agents": voted_agents,
|
|
168
|
-
"votes_needed_for_consensus": max(
|
|
169
|
-
1, int(votable_agents * self.consensus_threshold)
|
|
170
|
-
),
|
|
163
|
+
"votes_needed_for_consensus": max(1, int(votable_agents * self.consensus_threshold)),
|
|
171
164
|
"leading_agent": vote_counts.most_common(1)[0] if vote_counts else None,
|
|
172
165
|
}
|
|
173
166
|
|
|
@@ -181,19 +174,13 @@ class MassOrchestrator:
|
|
|
181
174
|
"status": state.status,
|
|
182
175
|
"update_times": len(state.updated_answers),
|
|
183
176
|
"chat_round": state.chat_round,
|
|
184
|
-
"vote_target": (
|
|
185
|
-
state.curr_vote.target_id if state.curr_vote else None
|
|
186
|
-
),
|
|
177
|
+
"vote_target": (state.curr_vote.target_id if state.curr_vote else None),
|
|
187
178
|
"execution_time": state.execution_time,
|
|
188
179
|
}
|
|
189
180
|
for agent_id, state in self.agent_states.items()
|
|
190
181
|
},
|
|
191
182
|
"voting_status": self._get_voting_status(),
|
|
192
|
-
"runtime": (
|
|
193
|
-
(time.time() - self.system_state.start_time)
|
|
194
|
-
if self.system_state.start_time
|
|
195
|
-
else 0
|
|
196
|
-
),
|
|
183
|
+
"runtime": ((time.time() - self.system_state.start_time) if self.system_state.start_time else 0),
|
|
197
184
|
}
|
|
198
185
|
|
|
199
186
|
def cast_vote(self, voter_id: int, target_id: int, reason: str = ""):
|
|
@@ -208,9 +195,7 @@ class MassOrchestrator:
|
|
|
208
195
|
with self._lock:
|
|
209
196
|
logger.info(f"🗳️ VOTING: Agent {voter_id} casting vote")
|
|
210
197
|
|
|
211
|
-
print(
|
|
212
|
-
f"🗳️ VOTE: Agent {voter_id} → Agent {target_id} ({self.system_state.phase})"
|
|
213
|
-
)
|
|
198
|
+
print(f"🗳️ VOTE: Agent {voter_id} → Agent {target_id} ({self.system_state.phase})")
|
|
214
199
|
if reason:
|
|
215
200
|
print(f" 📝 Voting reason: {len(reason)} chars")
|
|
216
201
|
|
|
@@ -225,9 +210,7 @@ class MassOrchestrator:
|
|
|
225
210
|
previous_vote = self.agent_states[voter_id].curr_vote
|
|
226
211
|
# Log vote change type
|
|
227
212
|
if previous_vote:
|
|
228
|
-
logger.info(
|
|
229
|
-
f" 🔄 Agent {voter_id} changed vote from Agent {previous_vote.target_id} to Agent {target_id}"
|
|
230
|
-
)
|
|
213
|
+
logger.info(f" 🔄 Agent {voter_id} changed vote from Agent {previous_vote.target_id} to Agent {target_id}")
|
|
231
214
|
else:
|
|
232
215
|
logger.info(f" ✨ Agent {voter_id} new vote for Agent {target_id}")
|
|
233
216
|
|
|
@@ -252,20 +235,14 @@ class MassOrchestrator:
|
|
|
252
235
|
# Update streaming display
|
|
253
236
|
if self.streaming_orchestrator:
|
|
254
237
|
self.streaming_orchestrator.update_agent_status(voter_id, "voted")
|
|
255
|
-
self.streaming_orchestrator.update_agent_vote_target(
|
|
256
|
-
voter_id, target_id
|
|
257
|
-
)
|
|
238
|
+
self.streaming_orchestrator.update_agent_vote_target(voter_id, target_id)
|
|
258
239
|
# Update agent update count
|
|
259
240
|
update_count = len(self.agent_states[voter_id].updated_answers)
|
|
260
|
-
self.streaming_orchestrator.update_agent_update_count(
|
|
261
|
-
voter_id, update_count
|
|
262
|
-
)
|
|
241
|
+
self.streaming_orchestrator.update_agent_update_count(voter_id, update_count)
|
|
263
242
|
# Update vote cast counts for all agents
|
|
264
243
|
for agent_id, agent_state in self.agent_states.items():
|
|
265
244
|
vote_cast_count = len(agent_state.cast_votes)
|
|
266
|
-
self.streaming_orchestrator.update_agent_votes_cast(
|
|
267
|
-
agent_id, vote_cast_count
|
|
268
|
-
)
|
|
245
|
+
self.streaming_orchestrator.update_agent_votes_cast(agent_id, vote_cast_count)
|
|
269
246
|
vote_counts = self._get_current_vote_counts()
|
|
270
247
|
self.streaming_orchestrator.update_vote_distribution(dict(vote_counts))
|
|
271
248
|
vote_msg = f"👍 Agent {voter_id} voted for Agent {target_id}"
|
|
@@ -291,18 +268,14 @@ class MassOrchestrator:
|
|
|
291
268
|
vote_counts = self._get_current_vote_counts()
|
|
292
269
|
voted_agents_count = self._get_current_voted_agents_count()
|
|
293
270
|
logger.info(f" 📊 Vote distribution: {dict(vote_counts)}")
|
|
294
|
-
logger.info(
|
|
295
|
-
f" 📈 Voting progress: {voted_agents_count}/{len(self.agent_states)} agents voted"
|
|
296
|
-
)
|
|
271
|
+
logger.info(f" 📈 Voting progress: {voted_agents_count}/{len(self.agent_states)} agents voted")
|
|
297
272
|
|
|
298
273
|
# Calculate consensus requirements
|
|
299
274
|
total_agents = len(self.agent_states)
|
|
300
275
|
votes_needed = max(1, int(total_agents * self.consensus_threshold))
|
|
301
276
|
if vote_counts:
|
|
302
277
|
leading_agent, leading_votes = vote_counts.most_common(1)[0]
|
|
303
|
-
logger.info(
|
|
304
|
-
f" 🏆 Leading: Agent {leading_agent} with {leading_votes} votes (need {votes_needed} for consensus)"
|
|
305
|
-
)
|
|
278
|
+
logger.info(f" 🏆 Leading: Agent {leading_agent} with {leading_votes} votes (need {votes_needed} for consensus)")
|
|
306
279
|
|
|
307
280
|
# Log event for internal tracking
|
|
308
281
|
self._log_event(
|
|
@@ -332,18 +305,15 @@ class MassOrchestrator:
|
|
|
332
305
|
self.streaming_orchestrator.add_system_message(answer_msg)
|
|
333
306
|
# Update agent update count
|
|
334
307
|
update_count = len(self.agent_states[agent_id].updated_answers)
|
|
335
|
-
self.streaming_orchestrator.update_agent_update_count(
|
|
336
|
-
agent_id, update_count
|
|
337
|
-
)
|
|
308
|
+
self.streaming_orchestrator.update_agent_update_count(agent_id, update_count)
|
|
338
309
|
|
|
339
310
|
# CRITICAL FIX: Restart voted agents when any agent shares new updates
|
|
340
311
|
with self._lock:
|
|
341
312
|
restarted_agents = []
|
|
342
|
-
|
|
313
|
+
time.time()
|
|
343
314
|
|
|
344
315
|
for other_agent_id, state in self.agent_states.items():
|
|
345
316
|
if other_agent_id != agent_id and state.status == "voted":
|
|
346
|
-
|
|
347
317
|
# Restart the voted agent
|
|
348
318
|
state.status = "working"
|
|
349
319
|
# This vote should be cleared as answers have been updated
|
|
@@ -351,28 +321,16 @@ class MassOrchestrator:
|
|
|
351
321
|
state.execution_start_time = time.time()
|
|
352
322
|
restarted_agents.append(other_agent_id)
|
|
353
323
|
|
|
354
|
-
logger.info(
|
|
355
|
-
f"🔄 Agent {other_agent_id} restarted due to update from Agent {agent_id}"
|
|
356
|
-
)
|
|
324
|
+
logger.info(f"🔄 Agent {other_agent_id} restarted due to update from Agent {agent_id}")
|
|
357
325
|
|
|
358
326
|
# Update streaming display
|
|
359
327
|
if self.streaming_orchestrator:
|
|
360
|
-
self.streaming_orchestrator.update_agent_status(
|
|
361
|
-
|
|
362
|
-
)
|
|
363
|
-
self.streaming_orchestrator.update_agent_vote_target(
|
|
364
|
-
other_agent_id, None
|
|
365
|
-
) # Clear vote target in display
|
|
328
|
+
self.streaming_orchestrator.update_agent_status(other_agent_id, "working")
|
|
329
|
+
self.streaming_orchestrator.update_agent_vote_target(other_agent_id, None) # Clear vote target in display
|
|
366
330
|
# Update agent update count for restarted agent
|
|
367
|
-
update_count = len(
|
|
368
|
-
|
|
369
|
-
|
|
370
|
-
self.streaming_orchestrator.update_agent_update_count(
|
|
371
|
-
other_agent_id, update_count
|
|
372
|
-
)
|
|
373
|
-
restart_msg = (
|
|
374
|
-
f"🔄 Agent {other_agent_id} restarted due to new update"
|
|
375
|
-
)
|
|
331
|
+
update_count = len(self.agent_states[other_agent_id].updated_answers)
|
|
332
|
+
self.streaming_orchestrator.update_agent_update_count(other_agent_id, update_count)
|
|
333
|
+
restart_msg = f"🔄 Agent {other_agent_id} restarted due to new update"
|
|
376
334
|
self.streaming_orchestrator.add_system_message(restart_msg)
|
|
377
335
|
|
|
378
336
|
# Log agent restart
|
|
@@ -391,15 +349,11 @@ class MassOrchestrator:
|
|
|
391
349
|
# Update vote distribution in streaming display
|
|
392
350
|
if self.streaming_orchestrator:
|
|
393
351
|
vote_counts = self._get_current_vote_counts()
|
|
394
|
-
self.streaming_orchestrator.update_vote_distribution(
|
|
395
|
-
dict(vote_counts)
|
|
396
|
-
)
|
|
352
|
+
self.streaming_orchestrator.update_vote_distribution(dict(vote_counts))
|
|
397
353
|
# Update vote cast counts for all agents to ensure accuracy
|
|
398
354
|
for agent_id, agent_state in self.agent_states.items():
|
|
399
355
|
vote_cast_count = len(agent_state.cast_votes)
|
|
400
|
-
self.streaming_orchestrator.update_agent_votes_cast(
|
|
401
|
-
agent_id, vote_cast_count
|
|
402
|
-
)
|
|
356
|
+
self.streaming_orchestrator.update_agent_votes_cast(agent_id, vote_cast_count)
|
|
403
357
|
|
|
404
358
|
return restarted_agents
|
|
405
359
|
|
|
@@ -410,9 +364,7 @@ class MassOrchestrator:
|
|
|
410
364
|
"""
|
|
411
365
|
with self._lock:
|
|
412
366
|
total_agents = len(self.agents)
|
|
413
|
-
failed_agents_count = len(
|
|
414
|
-
[s for s in self.agent_states.values() if s.status == "failed"]
|
|
415
|
-
)
|
|
367
|
+
failed_agents_count = len([s for s in self.agent_states.values() if s.status == "failed"])
|
|
416
368
|
votable_agents_count = total_agents - failed_agents_count
|
|
417
369
|
|
|
418
370
|
# Edge case: no votable agents
|
|
@@ -422,18 +374,10 @@ class MassOrchestrator:
|
|
|
422
374
|
|
|
423
375
|
# Edge case: only one votable agent
|
|
424
376
|
if votable_agents_count == 1:
|
|
425
|
-
working_agents = [
|
|
426
|
-
aid
|
|
427
|
-
for aid, state in self.agent_states.items()
|
|
428
|
-
if state.status == "working"
|
|
429
|
-
]
|
|
377
|
+
working_agents = [aid for aid, state in self.agent_states.items() if state.status == "working"]
|
|
430
378
|
if not working_agents: # The single agent has voted
|
|
431
379
|
# Find the single votable agent
|
|
432
|
-
votable_agent = [
|
|
433
|
-
aid
|
|
434
|
-
for aid, state in self.agent_states.items()
|
|
435
|
-
if state.status != "failed"
|
|
436
|
-
][0]
|
|
380
|
+
votable_agent = [aid for aid, state in self.agent_states.items() if state.status != "failed"][0]
|
|
437
381
|
logger.info(f"🎯 Single agent consensus: Agent {votable_agent}")
|
|
438
382
|
self._reach_consensus(votable_agent)
|
|
439
383
|
return True
|
|
@@ -448,14 +392,10 @@ class MassOrchestrator:
|
|
|
448
392
|
|
|
449
393
|
# Ensure the winning agent is still votable (not failed)
|
|
450
394
|
if self.agent_states[winning_agent_id].status == "failed":
|
|
451
|
-
logger.warning(
|
|
452
|
-
f"⚠️ Winning agent {winning_agent_id} has failed - recalculating"
|
|
453
|
-
)
|
|
395
|
+
logger.warning(f"⚠️ Winning agent {winning_agent_id} has failed - recalculating")
|
|
454
396
|
return False
|
|
455
397
|
|
|
456
|
-
logger.info(
|
|
457
|
-
f"✅ Consensus reached: Agent {winning_agent_id} with {winning_votes}/{votable_agents_count} votes"
|
|
458
|
-
)
|
|
398
|
+
logger.info(f"✅ Consensus reached: Agent {winning_agent_id} with {winning_votes}/{votable_agents_count} votes")
|
|
459
399
|
self._reach_consensus(winning_agent_id)
|
|
460
400
|
return True
|
|
461
401
|
|
|
@@ -487,11 +427,7 @@ class MassOrchestrator:
|
|
|
487
427
|
# Update streaming display
|
|
488
428
|
if self.streaming_orchestrator:
|
|
489
429
|
self.streaming_orchestrator.update_agent_status(agent_id, "failed")
|
|
490
|
-
failure_msg =
|
|
491
|
-
f"💥 Agent {agent_id} failed: {reason}"
|
|
492
|
-
if reason
|
|
493
|
-
else f"💥 Agent {agent_id} failed"
|
|
494
|
-
)
|
|
430
|
+
failure_msg = f"💥 Agent {agent_id} failed: {reason}" if reason else f"💥 Agent {agent_id} failed"
|
|
495
431
|
self.streaming_orchestrator.add_system_message(failure_msg)
|
|
496
432
|
|
|
497
433
|
# Log to the comprehensive logging system
|
|
@@ -515,13 +451,9 @@ class MassOrchestrator:
|
|
|
515
451
|
)
|
|
516
452
|
|
|
517
453
|
# Show current agent status distribution
|
|
518
|
-
status_counts = Counter(
|
|
519
|
-
state.status for state in self.agent_states.values()
|
|
520
|
-
)
|
|
454
|
+
status_counts = Counter(state.status for state in self.agent_states.values())
|
|
521
455
|
logger.info(f" 📊 Status distribution: {dict(status_counts)}")
|
|
522
|
-
logger.info(
|
|
523
|
-
f" 📈 Failed agents: {status_counts.get('failed', 0)}/{len(self.agent_states)} total"
|
|
524
|
-
)
|
|
456
|
+
logger.info(f" 📈 Failed agents: {status_counts.get('failed', 0)}/{len(self.agent_states)} total")
|
|
525
457
|
|
|
526
458
|
def _reach_consensus(self, winning_agent_id: int):
|
|
527
459
|
"""Mark consensus as reached and finalize the system."""
|
|
@@ -533,9 +465,7 @@ class MassOrchestrator:
|
|
|
533
465
|
# Update streaming orchestrator if available
|
|
534
466
|
if self.streaming_orchestrator:
|
|
535
467
|
vote_distribution = dict(self._get_current_vote_counts())
|
|
536
|
-
self.streaming_orchestrator.update_consensus_status(
|
|
537
|
-
winning_agent_id, vote_distribution
|
|
538
|
-
)
|
|
468
|
+
self.streaming_orchestrator.update_consensus_status(winning_agent_id, vote_distribution)
|
|
539
469
|
self.streaming_orchestrator.update_phase(old_phase, "consensus")
|
|
540
470
|
|
|
541
471
|
# Log to the comprehensive logging system
|
|
@@ -573,31 +503,17 @@ class MassOrchestrator:
|
|
|
573
503
|
"""
|
|
574
504
|
session_log = {
|
|
575
505
|
"session_metadata": {
|
|
576
|
-
"session_id": (
|
|
577
|
-
f"mass_session_{int(self.system_state.start_time)}"
|
|
578
|
-
if self.system_state.start_time
|
|
579
|
-
else None
|
|
580
|
-
),
|
|
506
|
+
"session_id": (f"mass_session_{int(self.system_state.start_time)}" if self.system_state.start_time else None),
|
|
581
507
|
"start_time": self.system_state.start_time,
|
|
582
508
|
"end_time": self.system_state.end_time,
|
|
583
|
-
"total_duration": (
|
|
584
|
-
(self.system_state.end_time - self.system_state.start_time)
|
|
585
|
-
if self.system_state.start_time and self.system_state.end_time
|
|
586
|
-
else None
|
|
587
|
-
),
|
|
509
|
+
"total_duration": ((self.system_state.end_time - self.system_state.start_time) if self.system_state.start_time and self.system_state.end_time else None),
|
|
588
510
|
"timestamp": datetime.now().isoformat(),
|
|
589
511
|
"system_version": "MassGen v1.0",
|
|
590
512
|
},
|
|
591
513
|
"task_information": {
|
|
592
|
-
"question": (
|
|
593
|
-
|
|
594
|
-
),
|
|
595
|
-
"task_id": (
|
|
596
|
-
self.system_state.task.task_id if self.system_state.task else None
|
|
597
|
-
),
|
|
598
|
-
"context": (
|
|
599
|
-
self.system_state.task.context if self.system_state.task else None
|
|
600
|
-
),
|
|
514
|
+
"question": (self.system_state.task.question if self.system_state.task else None),
|
|
515
|
+
"task_id": (self.system_state.task.task_id if self.system_state.task else None),
|
|
516
|
+
"context": (self.system_state.task.context if self.system_state.task else None),
|
|
601
517
|
},
|
|
602
518
|
"system_configuration": {
|
|
603
519
|
"max_duration": self.max_duration,
|
|
@@ -611,9 +527,7 @@ class MassOrchestrator:
|
|
|
611
527
|
"updates_count": len(state.updated_answers),
|
|
612
528
|
"chat_length": len(state.chat_history),
|
|
613
529
|
"chat_round": state.chat_round,
|
|
614
|
-
"vote_target": (
|
|
615
|
-
state.curr_vote.target_id if state.curr_vote else None
|
|
616
|
-
),
|
|
530
|
+
"vote_target": (state.curr_vote.target_id if state.curr_vote else None),
|
|
617
531
|
"execution_time": state.execution_time,
|
|
618
532
|
"execution_start_time": state.execution_start_time,
|
|
619
533
|
"execution_end_time": state.execution_end_time,
|
|
@@ -651,10 +565,7 @@ class MassOrchestrator:
|
|
|
651
565
|
{
|
|
652
566
|
"timestamp": entry["timestamp"],
|
|
653
567
|
"event_type": entry["event_type"],
|
|
654
|
-
"data_summary": {
|
|
655
|
-
k: (len(v) if isinstance(v, (str, list, dict)) else v)
|
|
656
|
-
for k, v in entry["data"].items()
|
|
657
|
-
},
|
|
568
|
+
"data_summary": {k: (len(v) if isinstance(v, (str, list, dict)) else v) for k, v in entry["data"].items()},
|
|
658
569
|
}
|
|
659
570
|
for entry in self.communication_log
|
|
660
571
|
],
|
|
@@ -711,9 +622,7 @@ class MassOrchestrator:
|
|
|
711
622
|
init_msg = f"🚀 Starting MassGen task with {len(self.agents)} agents"
|
|
712
623
|
self.streaming_orchestrator.add_system_message(init_msg)
|
|
713
624
|
|
|
714
|
-
self._log_event(
|
|
715
|
-
"task_started", {"task_id": task.task_id, "question": task.question}
|
|
716
|
-
)
|
|
625
|
+
self._log_event("task_started", {"task_id": task.task_id, "question": task.question})
|
|
717
626
|
logger.info("✅ Task initialization completed successfully")
|
|
718
627
|
|
|
719
628
|
# Run the workflow
|
|
@@ -764,17 +673,13 @@ class MassOrchestrator:
|
|
|
764
673
|
self.streaming_orchestrator.update_debate_rounds(debate_rounds)
|
|
765
674
|
|
|
766
675
|
if debate_rounds > self.max_debate_rounds:
|
|
767
|
-
logger.warning(
|
|
768
|
-
f"⚠️ Maximum debate rounds ({self.max_debate_rounds}) reached"
|
|
769
|
-
)
|
|
676
|
+
logger.warning(f"⚠️ Maximum debate rounds ({self.max_debate_rounds}) reached")
|
|
770
677
|
self._force_consensus_by_timeout()
|
|
771
678
|
# Representative will present final answer
|
|
772
679
|
self._present_final_answer(task)
|
|
773
680
|
break
|
|
774
681
|
|
|
775
|
-
logger.info(
|
|
776
|
-
f"🗣️ No consensus - starting debate round {debate_rounds}"
|
|
777
|
-
)
|
|
682
|
+
logger.info(f"🗣️ No consensus - starting debate round {debate_rounds}")
|
|
778
683
|
# Add debate instruction to the chat history and will be restarted in the next round
|
|
779
684
|
self._restart_all_agents_for_debate()
|
|
780
685
|
else:
|
|
@@ -795,9 +700,7 @@ class MassOrchestrator:
|
|
|
795
700
|
# Start all working agents
|
|
796
701
|
for agent_id in self.agents.keys():
|
|
797
702
|
if self.agent_states[agent_id].status not in ["failed"]:
|
|
798
|
-
self._start_agent_if_working(
|
|
799
|
-
agent_id, task, executor, active_futures
|
|
800
|
-
)
|
|
703
|
+
self._start_agent_if_working(agent_id, task, executor, active_futures)
|
|
801
704
|
|
|
802
705
|
# Monitor agents and handle restarts
|
|
803
706
|
while active_futures and not self._all_agents_voted():
|
|
@@ -819,13 +722,8 @@ class MassOrchestrator:
|
|
|
819
722
|
|
|
820
723
|
# Check for agents that need to restart (status changed back to "working")
|
|
821
724
|
for agent_id in self.agents.keys():
|
|
822
|
-
if
|
|
823
|
-
agent_id
|
|
824
|
-
and self.agent_states[agent_id].status == "working"
|
|
825
|
-
):
|
|
826
|
-
self._start_agent_if_working(
|
|
827
|
-
agent_id, task, executor, active_futures
|
|
828
|
-
)
|
|
725
|
+
if agent_id not in active_futures and self.agent_states[agent_id].status == "working":
|
|
726
|
+
self._start_agent_if_working(agent_id, task, executor, active_futures)
|
|
829
727
|
|
|
830
728
|
time.sleep(0.1) # Small delay to prevent busy waiting
|
|
831
729
|
|
|
@@ -843,11 +741,7 @@ class MassOrchestrator:
|
|
|
843
741
|
active_futures: Dict,
|
|
844
742
|
):
|
|
845
743
|
"""Start an agent if it's in working status and not already running."""
|
|
846
|
-
if
|
|
847
|
-
self.agent_states[agent_id].status == "working"
|
|
848
|
-
and agent_id not in active_futures
|
|
849
|
-
):
|
|
850
|
-
|
|
744
|
+
if self.agent_states[agent_id].status == "working" and agent_id not in active_futures:
|
|
851
745
|
self.agent_states[agent_id].execution_start_time = time.time()
|
|
852
746
|
future = executor.submit(self._run_single_agent, agent_id, task)
|
|
853
747
|
active_futures[agent_id] = future
|
|
@@ -868,18 +762,12 @@ class MassOrchestrator:
|
|
|
868
762
|
|
|
869
763
|
# Update streaming display with chat round
|
|
870
764
|
if self.streaming_orchestrator:
|
|
871
|
-
self.streaming_orchestrator.update_agent_chat_round(
|
|
872
|
-
agent_id, agent.state.chat_round
|
|
873
|
-
)
|
|
765
|
+
self.streaming_orchestrator.update_agent_chat_round(agent_id, agent.state.chat_round)
|
|
874
766
|
# Update agent update count
|
|
875
767
|
update_count = len(self.agent_states[agent_id].updated_answers)
|
|
876
|
-
self.streaming_orchestrator.update_agent_update_count(
|
|
877
|
-
agent_id, update_count
|
|
878
|
-
)
|
|
768
|
+
self.streaming_orchestrator.update_agent_update_count(agent_id, update_count)
|
|
879
769
|
|
|
880
|
-
logger.info(
|
|
881
|
-
f"✅ Agent {agent_id} completed work with status: {self.agent_states[agent_id].status}"
|
|
882
|
-
)
|
|
770
|
+
logger.info(f"✅ Agent {agent_id} completed work with status: {self.agent_states[agent_id].status}")
|
|
883
771
|
|
|
884
772
|
except Exception as e:
|
|
885
773
|
logger.error(f"❌ Agent {agent_id} failed: {e}")
|
|
@@ -887,14 +775,8 @@ class MassOrchestrator:
|
|
|
887
775
|
|
|
888
776
|
def _all_agents_voted(self) -> bool:
|
|
889
777
|
"""Check if all votable agents have voted."""
|
|
890
|
-
votable_agents = [
|
|
891
|
-
|
|
892
|
-
for aid, state in self.agent_states.items()
|
|
893
|
-
if state.status not in ["failed"]
|
|
894
|
-
]
|
|
895
|
-
voted_agents = [
|
|
896
|
-
aid for aid, state in self.agent_states.items() if state.status == "voted"
|
|
897
|
-
]
|
|
778
|
+
votable_agents = [aid for aid, state in self.agent_states.items() if state.status not in ["failed"]]
|
|
779
|
+
voted_agents = [aid for aid, state in self.agent_states.items() if state.status == "voted"]
|
|
898
780
|
|
|
899
781
|
return len(voted_agents) == len(votable_agents) and len(votable_agents) > 0
|
|
900
782
|
|
|
@@ -906,16 +788,11 @@ class MassOrchestrator:
|
|
|
906
788
|
logger.info("🔄 Restarting all agents for debate")
|
|
907
789
|
|
|
908
790
|
with self._lock:
|
|
909
|
-
|
|
910
791
|
# Update streaming display
|
|
911
792
|
if self.streaming_orchestrator:
|
|
912
793
|
self.streaming_orchestrator.reset_consensus()
|
|
913
|
-
self.streaming_orchestrator.update_phase(
|
|
914
|
-
|
|
915
|
-
)
|
|
916
|
-
self.streaming_orchestrator.add_system_message(
|
|
917
|
-
"🗣️ Starting debate phase - no consensus reached"
|
|
918
|
-
)
|
|
794
|
+
self.streaming_orchestrator.update_phase(self.system_state.phase, "collaboration")
|
|
795
|
+
self.streaming_orchestrator.add_system_message("🗣️ Starting debate phase - no consensus reached")
|
|
919
796
|
|
|
920
797
|
# Log debate start
|
|
921
798
|
if self.log_manager:
|
|
@@ -933,16 +810,14 @@ class MassOrchestrator:
|
|
|
933
810
|
# Note: We don't clear self.votes as it's a historical record
|
|
934
811
|
for agent_id, state in self.agent_states.items():
|
|
935
812
|
if state.status not in ["failed"]:
|
|
936
|
-
|
|
813
|
+
state.status
|
|
937
814
|
state.status = "working"
|
|
938
815
|
# We don't clear vote target when restarting for debate
|
|
939
816
|
# state.curr_vote = None
|
|
940
817
|
|
|
941
818
|
# Update streaming display for each agent
|
|
942
819
|
if self.streaming_orchestrator:
|
|
943
|
-
self.streaming_orchestrator.update_agent_status(
|
|
944
|
-
agent_id, "working"
|
|
945
|
-
)
|
|
820
|
+
self.streaming_orchestrator.update_agent_status(agent_id, "working")
|
|
946
821
|
|
|
947
822
|
# Log agent restart
|
|
948
823
|
if self.log_manager:
|
|
@@ -983,7 +858,7 @@ class MassOrchestrator:
|
|
|
983
858
|
{
|
|
984
859
|
"role": "system",
|
|
985
860
|
"content": """
|
|
986
|
-
You are given a task and multiple agents' answers and their votes.
|
|
861
|
+
You are given a task and multiple agents' answers and their votes.
|
|
987
862
|
Please incorporate these information and provide a final BEST answer to the original message.
|
|
988
863
|
""",
|
|
989
864
|
},
|
|
@@ -1022,22 +897,12 @@ The final answer must be self-contained, complete, well-sourced, compelling, and
|
|
|
1022
897
|
if vote_counts:
|
|
1023
898
|
# Select agent with most votes
|
|
1024
899
|
winning_agent_id = vote_counts.most_common(1)[0][0]
|
|
1025
|
-
logger.info(
|
|
1026
|
-
f" Selected Agent {winning_agent_id} with {vote_counts[winning_agent_id]} votes"
|
|
1027
|
-
)
|
|
900
|
+
logger.info(f" Selected Agent {winning_agent_id} with {vote_counts[winning_agent_id]} votes")
|
|
1028
901
|
else:
|
|
1029
902
|
# No votes - select first working agent
|
|
1030
|
-
working_agents = [
|
|
1031
|
-
|
|
1032
|
-
|
|
1033
|
-
if state.status == "working"
|
|
1034
|
-
]
|
|
1035
|
-
winning_agent_id = (
|
|
1036
|
-
working_agents[0] if working_agents else list(self.agents.keys())[0]
|
|
1037
|
-
)
|
|
1038
|
-
logger.info(
|
|
1039
|
-
f" No votes - selected Agent {winning_agent_id} as fallback"
|
|
1040
|
-
)
|
|
903
|
+
working_agents = [aid for aid, state in self.agent_states.items() if state.status == "working"]
|
|
904
|
+
winning_agent_id = working_agents[0] if working_agents else list(self.agents.keys())[0]
|
|
905
|
+
logger.info(f" No votes - selected Agent {winning_agent_id} as fallback")
|
|
1041
906
|
|
|
1042
907
|
self._reach_consensus(winning_agent_id)
|
|
1043
908
|
|
|
@@ -1051,11 +916,7 @@ The final answer must be self-contained, complete, well-sourced, compelling, and
|
|
|
1051
916
|
if not self.system_state.end_time:
|
|
1052
917
|
self.system_state.end_time = time.time()
|
|
1053
918
|
|
|
1054
|
-
session_duration =
|
|
1055
|
-
self.system_state.end_time - self.system_state.start_time
|
|
1056
|
-
if self.system_state.start_time
|
|
1057
|
-
else 0
|
|
1058
|
-
)
|
|
919
|
+
session_duration = self.system_state.end_time - self.system_state.start_time if self.system_state.start_time else 0
|
|
1059
920
|
|
|
1060
921
|
# Save final agent states to files
|
|
1061
922
|
if self.log_manager:
|
|
@@ -1066,7 +927,7 @@ The final answer must be self-contained, complete, well-sourced, compelling, and
|
|
|
1066
927
|
"consensus_reached": self.system_state.consensus_reached,
|
|
1067
928
|
"representative_agent_id": self.system_state.representative_agent_id,
|
|
1068
929
|
"session_duration": session_duration,
|
|
1069
|
-
}
|
|
930
|
+
},
|
|
1070
931
|
)
|
|
1071
932
|
|
|
1072
933
|
# Prepare clean, user-facing result
|
|
@@ -1077,9 +938,7 @@ The final answer must be self-contained, complete, well-sourced, compelling, and
|
|
|
1077
938
|
"session_duration": session_duration,
|
|
1078
939
|
"summary": {
|
|
1079
940
|
"total_agents": len(self.agents),
|
|
1080
|
-
"failed_agents": len(
|
|
1081
|
-
[s for s in self.agent_states.values() if s.status == "failed"]
|
|
1082
|
-
),
|
|
941
|
+
"failed_agents": len([s for s in self.agent_states.values() if s.status == "failed"]),
|
|
1083
942
|
"total_votes": len(self.votes),
|
|
1084
943
|
"final_vote_distribution": dict(self._get_current_vote_counts()),
|
|
1085
944
|
},
|