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/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
|
|
18
|
-
from collections import Counter
|
|
19
|
-
import textwrap
|
|
18
|
+
from typing import Any, Dict, List, Optional
|
|
20
19
|
|
|
21
|
-
from .types import
|
|
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(
|
|
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(
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
|
26
|
-
import os
|
|
26
|
+
import json
|
|
27
27
|
import logging
|
|
28
|
+
import os
|
|
29
|
+
import sys
|
|
28
30
|
import time
|
|
29
|
-
import
|
|
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 .
|
|
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 .
|
|
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":
|
|
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,
|