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/backends/oai.py
CHANGED
|
@@ -1,18 +1,13 @@
|
|
|
1
|
+
# -*- coding: utf-8 -*-
|
|
1
2
|
import os
|
|
2
|
-
import threading
|
|
3
|
-
import time
|
|
4
|
-
import json
|
|
5
|
-
import copy
|
|
6
3
|
|
|
7
4
|
from dotenv import load_dotenv
|
|
8
|
-
|
|
9
|
-
load_dotenv()
|
|
10
|
-
|
|
11
5
|
from openai import OpenAI
|
|
12
6
|
|
|
13
|
-
# Import utility functions
|
|
14
|
-
from massgen.v1.utils import function_to_json, execute_function_calls
|
|
15
7
|
from massgen.v1.types import AgentResponse
|
|
8
|
+
from massgen.v1.utils import function_to_json
|
|
9
|
+
|
|
10
|
+
load_dotenv()
|
|
16
11
|
|
|
17
12
|
|
|
18
13
|
def parse_completion(response, add_citations=True):
|
|
@@ -20,7 +15,10 @@ def parse_completion(response, add_citations=True):
|
|
|
20
15
|
|
|
21
16
|
Mainly three types of output in the response:
|
|
22
17
|
- reasoning (no summary provided): ResponseReasoningItem(id='rs_6876b0d566d08198ab9f992e1911bd0a02ec808107751c1f', summary=[], type='reasoning', status=None)
|
|
23
|
-
- web_search_call (actions: search, open_page, find_in_page):
|
|
18
|
+
- web_search_call (actions: search, open_page, find_in_page):
|
|
19
|
+
ResponseFunctionWebSearch(id='ws_6876b0e3b83081988d6cddd9770357c402ec808107751c1f',
|
|
20
|
+
status='completed', type='web_search_call',
|
|
21
|
+
action={'type': 'search', 'query': 'Economy of China Wikipedia GDP table'})
|
|
24
22
|
- message: response output (including text and citations, optional)
|
|
25
23
|
- code_interpreter_call (code provided): code output
|
|
26
24
|
- function_call: function call, arguments, and name provided
|
|
@@ -33,9 +31,7 @@ def parse_completion(response, add_citations=True):
|
|
|
33
31
|
|
|
34
32
|
# Process the response output
|
|
35
33
|
for r in response.output:
|
|
36
|
-
if (
|
|
37
|
-
r.type == "message"
|
|
38
|
-
): # Final response, including text and citations (optional)
|
|
34
|
+
if r.type == "message": # Final response, including text and citations (optional)
|
|
39
35
|
for c in r.content:
|
|
40
36
|
text += c.text
|
|
41
37
|
if add_citations and hasattr(c, "annotations") and c.annotations:
|
|
@@ -46,7 +42,7 @@ def parse_completion(response, add_citations=True):
|
|
|
46
42
|
"title": annotation.title,
|
|
47
43
|
"start_index": annotation.start_index,
|
|
48
44
|
"end_index": annotation.end_index,
|
|
49
|
-
}
|
|
45
|
+
},
|
|
50
46
|
)
|
|
51
47
|
elif r.type == "code_interpreter_call":
|
|
52
48
|
code.append(r.code)
|
|
@@ -54,9 +50,7 @@ def parse_completion(response, add_citations=True):
|
|
|
54
50
|
# detailed web search actions: search, open_page, find_in_page, etc
|
|
55
51
|
pass
|
|
56
52
|
elif r.type == "reasoning":
|
|
57
|
-
reasoning_items.append(
|
|
58
|
-
{"type": "reasoning", "id": r.id, "summary": r.summary}
|
|
59
|
-
)
|
|
53
|
+
reasoning_items.append({"type": "reasoning", "id": r.id, "summary": r.summary})
|
|
60
54
|
elif r.type == "function_call":
|
|
61
55
|
# tool output - include call_id for Responses API
|
|
62
56
|
function_calls.append(
|
|
@@ -66,7 +60,7 @@ def parse_completion(response, add_citations=True):
|
|
|
66
60
|
"arguments": r.arguments,
|
|
67
61
|
"call_id": getattr(r, "call_id", None),
|
|
68
62
|
"id": getattr(r, "id", None),
|
|
69
|
-
}
|
|
63
|
+
},
|
|
70
64
|
)
|
|
71
65
|
|
|
72
66
|
# Add citations to text if available
|
|
@@ -74,9 +68,7 @@ def parse_completion(response, add_citations=True):
|
|
|
74
68
|
try:
|
|
75
69
|
new_text = text
|
|
76
70
|
# Sort citations by end_index in descending order to avoid shifting issues when inserting
|
|
77
|
-
sorted_citations = sorted(
|
|
78
|
-
citations, key=lambda c: c["end_index"], reverse=True
|
|
79
|
-
)
|
|
71
|
+
sorted_citations = sorted(citations, key=lambda c: c["end_index"], reverse=True)
|
|
80
72
|
|
|
81
73
|
for idx, citation in enumerate(sorted_citations):
|
|
82
74
|
end_index = citation["end_index"]
|
|
@@ -86,9 +78,7 @@ def parse_completion(response, add_citations=True):
|
|
|
86
78
|
except Exception as e:
|
|
87
79
|
print(f"[OAI] Error adding citations to text: {e}")
|
|
88
80
|
|
|
89
|
-
return AgentResponse(
|
|
90
|
-
text=text, code=code, citations=citations, function_calls=function_calls
|
|
91
|
-
)
|
|
81
|
+
return AgentResponse(text=text, code=code, citations=citations, function_calls=function_calls)
|
|
92
82
|
|
|
93
83
|
|
|
94
84
|
def process_message(
|
|
@@ -150,9 +140,7 @@ def process_message(
|
|
|
150
140
|
elif tool == "live_search": # built-in tools
|
|
151
141
|
formatted_tools.append({"type": "web_search_preview"})
|
|
152
142
|
elif tool == "code_execution": # built-in tools
|
|
153
|
-
formatted_tools.append(
|
|
154
|
-
{"type": "code_interpreter", "container": {"type": "auto"}}
|
|
155
|
-
)
|
|
143
|
+
formatted_tools.append({"type": "code_interpreter", "container": {"type": "auto"}})
|
|
156
144
|
else:
|
|
157
145
|
raise ValueError(f"Invalid tool type: {type(tool)}")
|
|
158
146
|
|
|
@@ -165,10 +153,7 @@ def process_message(
|
|
|
165
153
|
instructions = message["content"]
|
|
166
154
|
else:
|
|
167
155
|
# Clean the function calls' id to avoid the requirements of related reasoning items
|
|
168
|
-
if (
|
|
169
|
-
message.get("type", "") == "function_call"
|
|
170
|
-
and message.get("id", None) is not None
|
|
171
|
-
):
|
|
156
|
+
if message.get("type", "") == "function_call" and message.get("id", None) is not None:
|
|
172
157
|
del message["id"]
|
|
173
158
|
input_text.append(message)
|
|
174
159
|
|
|
@@ -193,9 +178,7 @@ def process_message(
|
|
|
193
178
|
|
|
194
179
|
# CRITICAL: Include code interpreter outputs for streaming
|
|
195
180
|
# Without this, code execution results (stdout/stderr) won't be available
|
|
196
|
-
if formatted_tools and any(
|
|
197
|
-
tool.get("type") == "code_interpreter" for tool in formatted_tools
|
|
198
|
-
):
|
|
181
|
+
if formatted_tools and any(tool.get("type") == "code_interpreter" for tool in formatted_tools):
|
|
199
182
|
params["include"] = ["code_interpreter_call.outputs"]
|
|
200
183
|
|
|
201
184
|
# Only add temperature and top_p for models that support them
|
|
@@ -231,9 +214,7 @@ def process_message(
|
|
|
231
214
|
|
|
232
215
|
if completion is None:
|
|
233
216
|
# If we failed all retries, return empty response instead of raising exception
|
|
234
|
-
print(
|
|
235
|
-
f"Failed to get completion after {max_retries} retries, returning empty response"
|
|
236
|
-
)
|
|
217
|
+
print(f"Failed to get completion after {max_retries} retries, returning empty response")
|
|
237
218
|
return AgentResponse(text="", code=[], citations=[], function_calls=[])
|
|
238
219
|
|
|
239
220
|
# Handle Responses API response (same for all models)
|
|
@@ -268,9 +249,7 @@ def process_message(
|
|
|
268
249
|
elif chunk.type == "response.function_call_output.delta":
|
|
269
250
|
# Function call streaming
|
|
270
251
|
try:
|
|
271
|
-
stream_callback(
|
|
272
|
-
f"\n🔧 {chunk.delta if hasattr(chunk, 'delta') else 'Function call'}\n"
|
|
273
|
-
)
|
|
252
|
+
stream_callback(f"\n🔧 {chunk.delta if hasattr(chunk, 'delta') else 'Function call'}\n")
|
|
274
253
|
except Exception as e:
|
|
275
254
|
print(f"Stream callback error: {e}")
|
|
276
255
|
elif chunk.type == "response.function_call_output.done":
|
|
@@ -305,14 +284,9 @@ def process_message(
|
|
|
305
284
|
code_lines_shown += new_lines
|
|
306
285
|
|
|
307
286
|
# Check if we just exceeded 3 lines with this chunk
|
|
308
|
-
if
|
|
309
|
-
code_lines_shown >= 3
|
|
310
|
-
and not truncation_message_sent
|
|
311
|
-
):
|
|
287
|
+
if code_lines_shown >= 3 and not truncation_message_sent:
|
|
312
288
|
# Send truncation message for display only (not logging)
|
|
313
|
-
stream_callback(
|
|
314
|
-
"\n[CODE_DISPLAY_ONLY]\n💻 ... (full code in log file)\n"
|
|
315
|
-
)
|
|
289
|
+
stream_callback("\n[CODE_DISPLAY_ONLY]\n💻 ... (full code in log file)\n")
|
|
316
290
|
truncation_message_sent = True
|
|
317
291
|
else:
|
|
318
292
|
# Beyond 3 lines - send with special prefix for logging only
|
|
@@ -329,9 +303,7 @@ def process_message(
|
|
|
329
303
|
stream_callback("\n💻 Code writing completed\n")
|
|
330
304
|
except Exception as e:
|
|
331
305
|
print(f"Stream callback error: {e}")
|
|
332
|
-
elif
|
|
333
|
-
chunk.type == "response.code_interpreter_call_execution.in_progress"
|
|
334
|
-
):
|
|
306
|
+
elif chunk.type == "response.code_interpreter_call_execution.in_progress":
|
|
335
307
|
# Code execution started
|
|
336
308
|
try:
|
|
337
309
|
stream_callback("\n💻 Executing code...\n")
|
|
@@ -346,34 +318,22 @@ def process_message(
|
|
|
346
318
|
elif chunk.type == "response.output_item.added":
|
|
347
319
|
# New output item added
|
|
348
320
|
if hasattr(chunk, "item") and chunk.item:
|
|
349
|
-
if (
|
|
350
|
-
hasattr(chunk.item, "type")
|
|
351
|
-
and chunk.item.type == "web_search_call"
|
|
352
|
-
):
|
|
321
|
+
if hasattr(chunk.item, "type") and chunk.item.type == "web_search_call":
|
|
353
322
|
try:
|
|
354
323
|
stream_callback("\n🔍 Starting web search...\n")
|
|
355
324
|
except Exception as e:
|
|
356
325
|
print(f"Stream callback error: {e}")
|
|
357
|
-
elif (
|
|
358
|
-
hasattr(chunk.item, "type")
|
|
359
|
-
and chunk.item.type == "reasoning"
|
|
360
|
-
):
|
|
326
|
+
elif hasattr(chunk.item, "type") and chunk.item.type == "reasoning":
|
|
361
327
|
try:
|
|
362
328
|
stream_callback("\n🧠 Reasoning in progress...\n")
|
|
363
329
|
except Exception as e:
|
|
364
330
|
print(f"Stream callback error: {e}")
|
|
365
|
-
elif (
|
|
366
|
-
hasattr(chunk.item, "type")
|
|
367
|
-
and chunk.item.type == "code_interpreter_call"
|
|
368
|
-
):
|
|
331
|
+
elif hasattr(chunk.item, "type") and chunk.item.type == "code_interpreter_call":
|
|
369
332
|
try:
|
|
370
333
|
stream_callback("\n💻 Code interpreter starting...\n")
|
|
371
334
|
except Exception as e:
|
|
372
335
|
print(f"Stream callback error: {e}")
|
|
373
|
-
elif (
|
|
374
|
-
hasattr(chunk.item, "type")
|
|
375
|
-
and chunk.item.type == "function_call"
|
|
376
|
-
):
|
|
336
|
+
elif hasattr(chunk.item, "type") and chunk.item.type == "function_call":
|
|
377
337
|
# Function call started - create initial function call object
|
|
378
338
|
function_call_data = {
|
|
379
339
|
"type": "function_call",
|
|
@@ -389,50 +349,32 @@ def process_message(
|
|
|
389
349
|
# Notify function call started
|
|
390
350
|
function_name = function_call_data.get("name", "unknown")
|
|
391
351
|
try:
|
|
392
|
-
stream_callback(
|
|
393
|
-
f"\n🔧 Calling function '{function_name}'...\n"
|
|
394
|
-
)
|
|
352
|
+
stream_callback(f"\n🔧 Calling function '{function_name}'...\n")
|
|
395
353
|
except Exception as e:
|
|
396
354
|
print(f"Stream callback error: {e}")
|
|
397
355
|
elif chunk.type == "response.output_item.done":
|
|
398
356
|
# Check if this is a completed web search with query or reasoning completion
|
|
399
357
|
if hasattr(chunk, "item") and chunk.item:
|
|
400
|
-
if (
|
|
401
|
-
hasattr(chunk.item, "
|
|
402
|
-
and chunk.item.type == "web_search_call"
|
|
403
|
-
):
|
|
404
|
-
if hasattr(chunk.item, "action") and hasattr(
|
|
405
|
-
chunk.item.action, "query"
|
|
406
|
-
):
|
|
358
|
+
if hasattr(chunk.item, "type") and chunk.item.type == "web_search_call":
|
|
359
|
+
if hasattr(chunk.item, "action") and hasattr(chunk.item.action, "query"):
|
|
407
360
|
search_query = chunk.item.action.query
|
|
408
361
|
if search_query:
|
|
409
362
|
try:
|
|
410
|
-
stream_callback(
|
|
411
|
-
f"\n🔍 Completed search for: {search_query}\n"
|
|
412
|
-
)
|
|
363
|
+
stream_callback(f"\n🔍 Completed search for: {search_query}\n")
|
|
413
364
|
except Exception as e:
|
|
414
365
|
print(f"Stream callback error: {e}")
|
|
415
|
-
elif (
|
|
416
|
-
hasattr(chunk.item, "type")
|
|
417
|
-
and chunk.item.type == "reasoning"
|
|
418
|
-
):
|
|
366
|
+
elif hasattr(chunk.item, "type") and chunk.item.type == "reasoning":
|
|
419
367
|
try:
|
|
420
368
|
stream_callback("\n🧠 Reasoning completed\n")
|
|
421
369
|
except Exception as e:
|
|
422
370
|
print(f"Stream callback error: {e}")
|
|
423
|
-
elif (
|
|
424
|
-
hasattr(chunk.item, "type")
|
|
425
|
-
and chunk.item.type == "code_interpreter_call"
|
|
426
|
-
):
|
|
371
|
+
elif hasattr(chunk.item, "type") and chunk.item.type == "code_interpreter_call":
|
|
427
372
|
# CRITICAL: Capture code execution outputs (stdout/stderr)
|
|
428
373
|
# This is the actual result of running the code
|
|
429
374
|
if hasattr(chunk.item, "outputs") and chunk.item.outputs:
|
|
430
375
|
for output in chunk.item.outputs:
|
|
431
376
|
# Check if it's a dict-like object with a 'type' key (most common)
|
|
432
|
-
if (
|
|
433
|
-
hasattr(output, "get")
|
|
434
|
-
and output.get("type") == "logs"
|
|
435
|
-
):
|
|
377
|
+
if hasattr(output, "get") and output.get("type") == "logs":
|
|
436
378
|
logs_content = output.get("logs")
|
|
437
379
|
if logs_content:
|
|
438
380
|
# Add execution result to text output
|
|
@@ -443,10 +385,7 @@ def process_message(
|
|
|
443
385
|
except Exception as e:
|
|
444
386
|
print(f"Stream callback error: {e}")
|
|
445
387
|
# Also check for attribute-based access (fallback)
|
|
446
|
-
elif (
|
|
447
|
-
hasattr(output, "type")
|
|
448
|
-
and output.type == "logs"
|
|
449
|
-
):
|
|
388
|
+
elif hasattr(output, "type") and output.type == "logs":
|
|
450
389
|
if hasattr(output, "logs") and output.logs:
|
|
451
390
|
# Add execution result to text output
|
|
452
391
|
execution_result = f"\n[Code Execution Output]\n{output.logs}\n"
|
|
@@ -459,10 +398,7 @@ def process_message(
|
|
|
459
398
|
stream_callback("\n💻 Code interpreter completed\n")
|
|
460
399
|
except Exception as e:
|
|
461
400
|
print(f"Stream callback error: {e}")
|
|
462
|
-
elif (
|
|
463
|
-
hasattr(chunk.item, "type")
|
|
464
|
-
and chunk.item.type == "function_call"
|
|
465
|
-
):
|
|
401
|
+
elif hasattr(chunk.item, "type") and chunk.item.type == "function_call":
|
|
466
402
|
# Function call completed - update the function call data if needed
|
|
467
403
|
if hasattr(chunk.item, "arguments"):
|
|
468
404
|
# Find and update the corresponding function call
|
|
@@ -473,9 +409,7 @@ def process_message(
|
|
|
473
409
|
|
|
474
410
|
# Also update with accumulated arguments if available
|
|
475
411
|
if current_function_call and current_function_arguments:
|
|
476
|
-
current_function_call["arguments"] =
|
|
477
|
-
current_function_arguments
|
|
478
|
-
)
|
|
412
|
+
current_function_call["arguments"] = current_function_arguments
|
|
479
413
|
|
|
480
414
|
# Reset tracking
|
|
481
415
|
current_function_call = None
|
|
@@ -484,9 +418,7 @@ def process_message(
|
|
|
484
418
|
# Notify function call completed
|
|
485
419
|
function_name = getattr(chunk.item, "name", "unknown")
|
|
486
420
|
try:
|
|
487
|
-
stream_callback(
|
|
488
|
-
f"\n🔧 Function '{function_name}' completed\n"
|
|
489
|
-
)
|
|
421
|
+
stream_callback(f"\n🔧 Function '{function_name}' completed\n")
|
|
490
422
|
except Exception as e:
|
|
491
423
|
print(f"Stream callback error: {e}")
|
|
492
424
|
elif chunk.type == "response.web_search_call.in_progress":
|
|
@@ -510,9 +442,7 @@ def process_message(
|
|
|
510
442
|
citation_data = {
|
|
511
443
|
"url": getattr(chunk.annotation, "url", None),
|
|
512
444
|
"title": getattr(chunk.annotation, "title", None),
|
|
513
|
-
"start_index": getattr(
|
|
514
|
-
chunk.annotation, "start_index", None
|
|
515
|
-
),
|
|
445
|
+
"start_index": getattr(chunk.annotation, "start_index", None),
|
|
516
446
|
"end_index": getattr(chunk.annotation, "end_index", None),
|
|
517
447
|
}
|
|
518
448
|
citations.append(citation_data)
|
|
@@ -556,9 +486,7 @@ def process_message(
|
|
|
556
486
|
except Exception as e:
|
|
557
487
|
print(f"Stream callback error: {e}")
|
|
558
488
|
|
|
559
|
-
result = AgentResponse(
|
|
560
|
-
text=text, code=code, citations=citations, function_calls=function_calls
|
|
561
|
-
)
|
|
489
|
+
result = AgentResponse(text=text, code=code, citations=citations, function_calls=function_calls)
|
|
562
490
|
else:
|
|
563
491
|
# Parse non-streaming response using existing parse_completion function
|
|
564
492
|
result = parse_completion(completion, add_citations=True)
|
massgen/v1/cli.py
CHANGED
|
@@ -19,19 +19,18 @@ Usage examples:
|
|
|
19
19
|
|
|
20
20
|
import argparse
|
|
21
21
|
import sys
|
|
22
|
-
import os
|
|
23
22
|
from pathlib import Path
|
|
24
23
|
|
|
25
|
-
# Add massgen package to path
|
|
26
|
-
sys.path.insert(0, str(Path(__file__).parent))
|
|
27
|
-
|
|
28
24
|
from massgen.v1 import (
|
|
29
|
-
run_mass_with_config,
|
|
30
|
-
load_config_from_yaml,
|
|
31
|
-
create_config_from_models,
|
|
32
25
|
ConfigurationError,
|
|
26
|
+
create_config_from_models,
|
|
27
|
+
load_config_from_yaml,
|
|
28
|
+
run_mass_with_config,
|
|
33
29
|
)
|
|
34
30
|
|
|
31
|
+
# Add massgen package to path
|
|
32
|
+
sys.path.insert(0, str(Path(__file__).parent))
|
|
33
|
+
|
|
35
34
|
# Color constants for beautiful terminal output
|
|
36
35
|
BRIGHT_CYAN = "\033[96m"
|
|
37
36
|
BRIGHT_BLUE = "\033[94m"
|
|
@@ -50,9 +49,7 @@ def display_vote_distribution(vote_distribution):
|
|
|
50
49
|
# sort the keys
|
|
51
50
|
sorted_keys = sorted(vote_distribution.keys())
|
|
52
51
|
for agent_id in sorted_keys:
|
|
53
|
-
print(
|
|
54
|
-
f" {BRIGHT_CYAN}Agent {agent_id}{RESET}: {BRIGHT_GREEN}{vote_distribution[agent_id]}{RESET} votes"
|
|
55
|
-
)
|
|
52
|
+
print(f" {BRIGHT_CYAN}Agent {agent_id}{RESET}: {BRIGHT_GREEN}{vote_distribution[agent_id]}{RESET} votes")
|
|
56
53
|
|
|
57
54
|
|
|
58
55
|
def run_interactive_mode(config):
|
|
@@ -69,17 +66,9 @@ def run_interactive_mode(config):
|
|
|
69
66
|
if hasattr(config, "agents") and config.agents:
|
|
70
67
|
print(f"🤖 Agents ({len(config.agents)}):")
|
|
71
68
|
for i, agent in enumerate(config.agents, 1):
|
|
72
|
-
model_name = (
|
|
73
|
-
getattr(agent.model_config, "model", "Unknown")
|
|
74
|
-
if hasattr(agent, "model_config")
|
|
75
|
-
else "Unknown"
|
|
76
|
-
)
|
|
69
|
+
model_name = getattr(agent.model_config, "model", "Unknown") if hasattr(agent, "model_config") else "Unknown"
|
|
77
70
|
agent_type = getattr(agent, "agent_type", "Unknown")
|
|
78
|
-
tools = (
|
|
79
|
-
getattr(agent.model_config, "tools", [])
|
|
80
|
-
if hasattr(agent, "model_config")
|
|
81
|
-
else []
|
|
82
|
-
)
|
|
71
|
+
tools = getattr(agent.model_config, "tools", []) if hasattr(agent, "model_config") else []
|
|
83
72
|
tools_str = ", ".join(tools) if tools else "None"
|
|
84
73
|
print(f" {i}. {model_name} ({agent_type})")
|
|
85
74
|
print(f" Tools: {tools_str}")
|
|
@@ -89,21 +78,15 @@ def run_interactive_mode(config):
|
|
|
89
78
|
# Show orchestrator settings
|
|
90
79
|
if hasattr(config, "orchestrator"):
|
|
91
80
|
orch = config.orchestrator
|
|
92
|
-
print(
|
|
81
|
+
print("⚙️ Orchestrator:")
|
|
93
82
|
print(f" • Duration: {getattr(orch, 'max_duration', 'Default')}s")
|
|
94
83
|
print(f" • Consensus: {getattr(orch, 'consensus_threshold', 'Default')}")
|
|
95
|
-
print(
|
|
96
|
-
f" • Max Debate Rounds: {getattr(orch, 'max_debate_rounds', 'Default')}"
|
|
97
|
-
)
|
|
84
|
+
print(f" • Max Debate Rounds: {getattr(orch, 'max_debate_rounds', 'Default')}")
|
|
98
85
|
|
|
99
86
|
# Show model parameters (from first agent as representative)
|
|
100
|
-
if (
|
|
101
|
-
hasattr(config, "agents")
|
|
102
|
-
and config.agents
|
|
103
|
-
and hasattr(config.agents[0], "model_config")
|
|
104
|
-
):
|
|
87
|
+
if hasattr(config, "agents") and config.agents and hasattr(config.agents[0], "model_config"):
|
|
105
88
|
model_config = config.agents[0].model_config
|
|
106
|
-
print(
|
|
89
|
+
print("🔧 Model Config:")
|
|
107
90
|
temp = getattr(model_config, "temperature", "Default")
|
|
108
91
|
timeout = getattr(model_config, "inference_timeout", "Default")
|
|
109
92
|
max_rounds = getattr(model_config, "max_rounds", "Default")
|
|
@@ -114,12 +97,8 @@ def run_interactive_mode(config):
|
|
|
114
97
|
# Show display settings
|
|
115
98
|
if hasattr(config, "streaming_display"):
|
|
116
99
|
display = config.streaming_display
|
|
117
|
-
display_status = (
|
|
118
|
-
|
|
119
|
-
)
|
|
120
|
-
logs_status = (
|
|
121
|
-
"✅ Enabled" if getattr(display, "save_logs", True) else "❌ Disabled"
|
|
122
|
-
)
|
|
100
|
+
display_status = "✅ Enabled" if getattr(display, "display_enabled", True) else "❌ Disabled"
|
|
101
|
+
logs_status = "✅ Enabled" if getattr(display, "save_logs", True) else "❌ Disabled"
|
|
123
102
|
print(f"📺 Display: {display_status}")
|
|
124
103
|
print(f"📁 Logs: {logs_status}")
|
|
125
104
|
|
|
@@ -162,48 +141,27 @@ def run_interactive_mode(config):
|
|
|
162
141
|
# Assistant response section
|
|
163
142
|
print(f"\n{BRIGHT_GREEN}🤖 Assistant:{RESET}")
|
|
164
143
|
|
|
165
|
-
agents = {
|
|
166
|
-
f"Agent {agent.agent_id}": agent.model_config.model
|
|
167
|
-
for agent in config.agents
|
|
168
|
-
}
|
|
144
|
+
agents = {f"Agent {agent.agent_id}": agent.model_config.model for agent in config.agents}
|
|
169
145
|
|
|
170
146
|
# Show metadata with clean indentation
|
|
171
147
|
if result.get("single_agent_mode", False):
|
|
172
148
|
print(f" {BRIGHT_YELLOW}📋 Mode:{RESET} Single Agent")
|
|
173
149
|
print(f" {BRIGHT_MAGENTA}🤖 Agents:{RESET} {agents}")
|
|
174
|
-
print(
|
|
175
|
-
|
|
176
|
-
)
|
|
177
|
-
print(
|
|
178
|
-
f" {BRIGHT_GREEN}🔧 Model:{RESET} {result.get('model_used', 'Unknown')}"
|
|
179
|
-
)
|
|
180
|
-
print(
|
|
181
|
-
f" {BRIGHT_BLUE}⏱️ Duration:{RESET} {result['session_duration']:.1f}s"
|
|
182
|
-
)
|
|
150
|
+
print(f" {BRIGHT_CYAN}🎯 Representative:{RESET} {result['representative_agent_id']}")
|
|
151
|
+
print(f" {BRIGHT_GREEN}🔧 Model:{RESET} {result.get('model_used', 'Unknown')}")
|
|
152
|
+
print(f" {BRIGHT_BLUE}⏱️ Duration:{RESET} {result['session_duration']:.1f}s")
|
|
183
153
|
if result.get("citations"):
|
|
184
|
-
print(
|
|
185
|
-
f" {BRIGHT_WHITE}📚 Citations:{RESET} {len(result['citations'])}"
|
|
186
|
-
)
|
|
154
|
+
print(f" {BRIGHT_WHITE}📚 Citations:{RESET} {len(result['citations'])}")
|
|
187
155
|
if result.get("code"):
|
|
188
|
-
print(
|
|
189
|
-
f" {BRIGHT_WHITE}💻 Code blocks:{RESET} {len(result['code'])}"
|
|
190
|
-
)
|
|
156
|
+
print(f" {BRIGHT_WHITE}💻 Code blocks:{RESET} {len(result['code'])}")
|
|
191
157
|
else:
|
|
192
158
|
print(f" {BRIGHT_YELLOW}📋 Mode:{RESET} Multi-Agent")
|
|
193
159
|
print(f" {BRIGHT_MAGENTA}🤖 Agents:{RESET} {agents}")
|
|
194
|
-
print(
|
|
195
|
-
|
|
196
|
-
)
|
|
197
|
-
print(
|
|
198
|
-
f" {BRIGHT_GREEN}✅ Consensus:{RESET} {result['consensus_reached']}"
|
|
199
|
-
)
|
|
200
|
-
print(
|
|
201
|
-
f" {BRIGHT_BLUE}⏱️ Duration:{RESET} {result['session_duration']:.1f}s"
|
|
202
|
-
)
|
|
160
|
+
print(f" {BRIGHT_CYAN}🎯 Representative:{RESET} {result['representative_agent_id']}")
|
|
161
|
+
print(f" {BRIGHT_GREEN}✅ Consensus:{RESET} {result['consensus_reached']}")
|
|
162
|
+
print(f" {BRIGHT_BLUE}⏱️ Duration:{RESET} {result['session_duration']:.1f}s")
|
|
203
163
|
print(f" {BRIGHT_YELLOW}📊 Vote Distribution:{RESET}")
|
|
204
|
-
display_vote_distribution(
|
|
205
|
-
result["summary"]["final_vote_distribution"]
|
|
206
|
-
)
|
|
164
|
+
display_vote_distribution(result["summary"]["final_vote_distribution"])
|
|
207
165
|
|
|
208
166
|
# Print the response with simple indentation
|
|
209
167
|
print(f"\n {BRIGHT_RED}💡 Response:{RESET}")
|
|
@@ -233,14 +191,14 @@ def main():
|
|
|
233
191
|
Examples:
|
|
234
192
|
# Use YAML configuration
|
|
235
193
|
uv run python -m massgen.v1.cli "What is the capital of France?" --config examples/production.yaml
|
|
236
|
-
|
|
194
|
+
|
|
237
195
|
# Use model names directly (single or multiple agents)
|
|
238
196
|
uv run python -m massgen.v1.cli "What is 2+2?" --models gpt-4o gemini-2.5-flash
|
|
239
197
|
uv run python -m massgen.v1.cli "What is 2+2?" --models gpt-4o # Single agent mode
|
|
240
|
-
|
|
198
|
+
|
|
241
199
|
# Interactive mode (no question provided)
|
|
242
200
|
uv run python -m massgen.v1.cli --models gpt-4o grok-4
|
|
243
|
-
|
|
201
|
+
|
|
244
202
|
# Override parameters
|
|
245
203
|
uv run python -m massgen.v1.cli "Question" --models gpt-4o gemini-2.5-flash --max-duration 1200 --consensus 0.8
|
|
246
204
|
""",
|
|
@@ -255,26 +213,14 @@ Examples:
|
|
|
255
213
|
|
|
256
214
|
# Configuration options (mutually exclusive)
|
|
257
215
|
config_group = parser.add_mutually_exclusive_group(required=True)
|
|
258
|
-
config_group.add_argument(
|
|
259
|
-
|
|
260
|
-
)
|
|
261
|
-
config_group.add_argument(
|
|
262
|
-
"--models", nargs="+", help="Model names (e.g., gpt-4o gemini-2.5-flash)"
|
|
263
|
-
)
|
|
216
|
+
config_group.add_argument("--config", type=str, help="Path to YAML configuration file")
|
|
217
|
+
config_group.add_argument("--models", nargs="+", help="Model names (e.g., gpt-4o gemini-2.5-flash)")
|
|
264
218
|
|
|
265
219
|
# Configuration overrides
|
|
266
|
-
parser.add_argument(
|
|
267
|
-
|
|
268
|
-
)
|
|
269
|
-
parser.add_argument(
|
|
270
|
-
"--consensus", type=float, default=None, help="Consensus threshold (0.0-1.0)"
|
|
271
|
-
)
|
|
272
|
-
parser.add_argument(
|
|
273
|
-
"--max-debates", type=int, default=None, help="Maximum debate rounds"
|
|
274
|
-
)
|
|
275
|
-
parser.add_argument(
|
|
276
|
-
"--no-display", action="store_true", help="Disable streaming display"
|
|
277
|
-
)
|
|
220
|
+
parser.add_argument("--max-duration", type=int, default=None, help="Max duration in seconds")
|
|
221
|
+
parser.add_argument("--consensus", type=float, default=None, help="Consensus threshold (0.0-1.0)")
|
|
222
|
+
parser.add_argument("--max-debates", type=int, default=None, help="Maximum debate rounds")
|
|
223
|
+
parser.add_argument("--no-display", action="store_true", help="Disable streaming display")
|
|
278
224
|
parser.add_argument("--no-logs", action="store_true", help="Disable file logging")
|
|
279
225
|
|
|
280
226
|
args = parser.parse_args()
|
|
@@ -302,10 +248,7 @@ Examples:
|
|
|
302
248
|
config.validate()
|
|
303
249
|
|
|
304
250
|
# The used models
|
|
305
|
-
agents = {
|
|
306
|
-
f"Agent {agent.agent_id}": agent.model_config.model
|
|
307
|
-
for agent in config.agents
|
|
308
|
-
}
|
|
251
|
+
agents = {f"Agent {agent.agent_id}": agent.model_config.model for agent in config.agents}
|
|
309
252
|
|
|
310
253
|
# Check if question was provided
|
|
311
254
|
if args.question:
|
|
@@ -333,7 +276,7 @@ Examples:
|
|
|
333
276
|
print(f"🎯 Representative Agent: {result['representative_agent_id']}")
|
|
334
277
|
print(f"✅ Consensus: {result['consensus_reached']}")
|
|
335
278
|
print(f"⏱️ Duration: {result['session_duration']:.1f}s")
|
|
336
|
-
print(
|
|
279
|
+
print("📊 Votes:")
|
|
337
280
|
display_vote_distribution(result["summary"]["final_vote_distribution"])
|
|
338
281
|
else:
|
|
339
282
|
# Interactive mode
|
massgen/v1/config.py
CHANGED
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
# -*- coding: utf-8 -*-
|
|
1
2
|
"""
|
|
2
3
|
MassGen Configuration System
|
|
3
4
|
|
|
@@ -5,27 +6,24 @@ This module provides configuration management for the MassGen system,
|
|
|
5
6
|
supporting YAML file loading and programmatic configuration creation.
|
|
6
7
|
"""
|
|
7
8
|
|
|
8
|
-
import yaml
|
|
9
|
-
import os
|
|
10
9
|
from pathlib import Path
|
|
11
|
-
from typing import Dict, List,
|
|
12
|
-
|
|
10
|
+
from typing import Any, Dict, List, Optional, Union
|
|
11
|
+
|
|
12
|
+
import yaml
|
|
13
13
|
|
|
14
14
|
from .types import (
|
|
15
|
-
MassConfig,
|
|
16
|
-
OrchestratorConfig,
|
|
17
15
|
AgentConfig,
|
|
16
|
+
LoggingConfig,
|
|
17
|
+
MassConfig,
|
|
18
18
|
ModelConfig,
|
|
19
|
+
OrchestratorConfig,
|
|
19
20
|
StreamingDisplayConfig,
|
|
20
|
-
LoggingConfig,
|
|
21
21
|
)
|
|
22
22
|
|
|
23
23
|
|
|
24
24
|
class ConfigurationError(Exception):
|
|
25
25
|
"""Exception raised for configuration-related errors."""
|
|
26
26
|
|
|
27
|
-
pass
|
|
28
|
-
|
|
29
27
|
|
|
30
28
|
def load_config_from_yaml(config_path: Union[str, Path]) -> MassConfig:
|
|
31
29
|
"""
|
|
@@ -92,9 +90,7 @@ def create_config_from_models(
|
|
|
92
90
|
inference_timeout=180,
|
|
93
91
|
)
|
|
94
92
|
|
|
95
|
-
agent_config = AgentConfig(
|
|
96
|
-
agent_id=i + 1, agent_type=agent_type, model_config=model_config
|
|
97
|
-
)
|
|
93
|
+
agent_config = AgentConfig(agent_id=i + 1, agent_type=agent_type, model_config=model_config)
|
|
98
94
|
agents.append(agent_config)
|
|
99
95
|
|
|
100
96
|
# Create configuration components
|