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
|
@@ -0,0 +1,142 @@
|
|
|
1
|
+
#!/usr/bin/env python3
|
|
2
|
+
# -*- coding: utf-8 -*-
|
|
3
|
+
"""
|
|
4
|
+
Test script to verify ChatCompletionsBackend refactoring.
|
|
5
|
+
Tests integration with different OpenAI-compatible providers.
|
|
6
|
+
"""
|
|
7
|
+
|
|
8
|
+
import asyncio
|
|
9
|
+
import os
|
|
10
|
+
|
|
11
|
+
from massgen.backend import ChatCompletionsBackend
|
|
12
|
+
|
|
13
|
+
|
|
14
|
+
async def test_openai_backend():
|
|
15
|
+
"""Test ChatCompletionsBackend with OpenAI."""
|
|
16
|
+
print("🔧 Testing ChatCompletionsBackend with OpenAI...")
|
|
17
|
+
|
|
18
|
+
# Create backend with OpenAI defaults
|
|
19
|
+
backend = ChatCompletionsBackend()
|
|
20
|
+
print(f"Provider: {backend.get_provider_name()}")
|
|
21
|
+
print(f"Base URL: {backend.base_url}")
|
|
22
|
+
print(f"API Key configured: {'Yes' if backend.api_key else 'No'}")
|
|
23
|
+
|
|
24
|
+
# Test token estimation
|
|
25
|
+
test_text = "Hello world, how are you doing today?"
|
|
26
|
+
tokens = backend.estimate_tokens(test_text)
|
|
27
|
+
print(f"Estimated tokens for '{test_text}': {tokens}")
|
|
28
|
+
|
|
29
|
+
# Test cost calculation
|
|
30
|
+
cost = backend.calculate_cost(1000, 500, "gpt-4o-mini")
|
|
31
|
+
print(f"Cost for 1000 input + 500 output tokens (gpt-4o-mini): ${cost:.4f}")
|
|
32
|
+
|
|
33
|
+
|
|
34
|
+
async def test_together_ai_backend():
|
|
35
|
+
"""Test ChatCompletionsBackend configured for Together AI."""
|
|
36
|
+
print("\n🔧 Testing ChatCompletionsBackend with Together AI...")
|
|
37
|
+
|
|
38
|
+
# Create backend configured for Together AI
|
|
39
|
+
backend = ChatCompletionsBackend(
|
|
40
|
+
base_url="https://api.together.xyz/v1",
|
|
41
|
+
provider_name="Together AI",
|
|
42
|
+
api_key=os.getenv("TOGETHER_API_KEY"),
|
|
43
|
+
)
|
|
44
|
+
print(f"Provider: {backend.get_provider_name()}")
|
|
45
|
+
print(f"Base URL: {backend.base_url}")
|
|
46
|
+
print(f"API Key configured: {'Yes' if backend.api_key else 'No'}")
|
|
47
|
+
|
|
48
|
+
# Test cost calculation with Together AI model
|
|
49
|
+
cost = backend.calculate_cost(1000, 500, "meta-llama/Meta-Llama-3.1-8B-Instruct-Turbo")
|
|
50
|
+
print(f"Cost for 1000 input + 500 output tokens (fallback pricing): ${cost:.4f}")
|
|
51
|
+
|
|
52
|
+
|
|
53
|
+
async def test_cerebras_backend():
|
|
54
|
+
"""Test ChatCompletionsBackend configured for Cerebras AI."""
|
|
55
|
+
print("\n🔧 Testing ChatCompletionsBackend with Cerebras AI...")
|
|
56
|
+
|
|
57
|
+
# Create backend configured for Cerebras AI
|
|
58
|
+
backend = ChatCompletionsBackend(
|
|
59
|
+
base_url="https://api.cerebras.ai/v1",
|
|
60
|
+
provider_name="Cerebras AI",
|
|
61
|
+
api_key=os.getenv("CEREBRAS_API_KEY"),
|
|
62
|
+
)
|
|
63
|
+
print(f"Provider: {backend.get_provider_name()}")
|
|
64
|
+
print(f"Base URL: {backend.base_url}")
|
|
65
|
+
print(f"API Key configured: {'Yes' if backend.api_key else 'No'}")
|
|
66
|
+
|
|
67
|
+
|
|
68
|
+
async def test_tool_conversion():
|
|
69
|
+
"""Test tool format conversion."""
|
|
70
|
+
print("\n🔧 Testing tool format conversion...")
|
|
71
|
+
|
|
72
|
+
backend = ChatCompletionsBackend()
|
|
73
|
+
|
|
74
|
+
# Test Response API format conversion
|
|
75
|
+
response_tools = [
|
|
76
|
+
{
|
|
77
|
+
"type": "function",
|
|
78
|
+
"name": "get_weather",
|
|
79
|
+
"description": "Get weather information",
|
|
80
|
+
"parameters": {
|
|
81
|
+
"type": "object",
|
|
82
|
+
"properties": {"location": {"type": "string"}},
|
|
83
|
+
"required": ["location"],
|
|
84
|
+
},
|
|
85
|
+
},
|
|
86
|
+
]
|
|
87
|
+
|
|
88
|
+
converted = backend.convert_tools_to_chat_completions_format(response_tools)
|
|
89
|
+
print("Response API tools converted to Chat Completions format:")
|
|
90
|
+
print(f" Original: {response_tools[0]}")
|
|
91
|
+
print(f" Converted: {converted[0]}")
|
|
92
|
+
|
|
93
|
+
# Test Chat Completions format (should remain unchanged)
|
|
94
|
+
chat_tools = [
|
|
95
|
+
{
|
|
96
|
+
"type": "function",
|
|
97
|
+
"function": {
|
|
98
|
+
"name": "search_web",
|
|
99
|
+
"description": "Search the web",
|
|
100
|
+
"parameters": {
|
|
101
|
+
"type": "object",
|
|
102
|
+
"properties": {"query": {"type": "string"}},
|
|
103
|
+
"required": ["query"],
|
|
104
|
+
},
|
|
105
|
+
},
|
|
106
|
+
},
|
|
107
|
+
]
|
|
108
|
+
|
|
109
|
+
converted_chat = backend.convert_tools_to_chat_completions_format(chat_tools)
|
|
110
|
+
print("\nChat Completions tools (should remain unchanged):")
|
|
111
|
+
print(f" Original: {chat_tools[0]}")
|
|
112
|
+
print(f" After conversion: {converted_chat[0]}")
|
|
113
|
+
|
|
114
|
+
|
|
115
|
+
async def main():
|
|
116
|
+
"""Run all tests."""
|
|
117
|
+
print("🚀 Testing ChatCompletionsBackend refactoring...")
|
|
118
|
+
print("=" * 60)
|
|
119
|
+
|
|
120
|
+
try:
|
|
121
|
+
await test_openai_backend()
|
|
122
|
+
await test_together_ai_backend()
|
|
123
|
+
await test_cerebras_backend()
|
|
124
|
+
await test_tool_conversion()
|
|
125
|
+
|
|
126
|
+
print("\n" + "=" * 60)
|
|
127
|
+
print("✅ All tests completed successfully!")
|
|
128
|
+
print("\n📋 ChatCompletionsBackend is now ready for use with:")
|
|
129
|
+
print(" • OpenAI (default)")
|
|
130
|
+
print(" • Together AI")
|
|
131
|
+
print(" • Cerebras AI")
|
|
132
|
+
print(" • Any OpenAI-compatible provider")
|
|
133
|
+
|
|
134
|
+
except Exception as e:
|
|
135
|
+
print(f"\n❌ Test failed: {e}")
|
|
136
|
+
return 1
|
|
137
|
+
|
|
138
|
+
return 0
|
|
139
|
+
|
|
140
|
+
|
|
141
|
+
if __name__ == "__main__":
|
|
142
|
+
exit(asyncio.run(main()))
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
#!/usr/bin/env python3
|
|
2
|
+
# -*- coding: utf-8 -*-
|
|
2
3
|
"""
|
|
3
4
|
Claude Backend Integration Tests for MassGen
|
|
4
5
|
|
|
@@ -12,18 +13,16 @@ Tests the Claude backend implementation with real API calls:
|
|
|
12
13
|
Requires ANTHROPIC_API_KEY environment variable.
|
|
13
14
|
"""
|
|
14
15
|
|
|
16
|
+
import asyncio
|
|
15
17
|
import os
|
|
16
18
|
import sys
|
|
17
|
-
import asyncio
|
|
18
|
-
import json
|
|
19
19
|
from pathlib import Path
|
|
20
20
|
|
|
21
21
|
# Add project root to path
|
|
22
22
|
project_root = Path(__file__).parent.parent.parent.parent
|
|
23
23
|
sys.path.insert(0, str(project_root))
|
|
24
24
|
|
|
25
|
-
from massgen.backend.
|
|
26
|
-
from massgen.backend.base import StreamChunk
|
|
25
|
+
from massgen.backend.claude import ClaudeBackend # noqa: E402
|
|
27
26
|
|
|
28
27
|
|
|
29
28
|
async def test_claude_basic_streaming():
|
|
@@ -32,21 +31,15 @@ async def test_claude_basic_streaming():
|
|
|
32
31
|
|
|
33
32
|
backend = ClaudeBackend()
|
|
34
33
|
|
|
35
|
-
messages = [
|
|
36
|
-
{"role": "user", "content": "Explain quantum computing in 2-3 sentences."}
|
|
37
|
-
]
|
|
34
|
+
messages = [{"role": "user", "content": "Explain quantum computing in 2-3 sentences."}]
|
|
38
35
|
|
|
39
36
|
content = ""
|
|
40
|
-
async for chunk in backend.stream_with_tools(
|
|
41
|
-
messages, [], model="claude-3-5-haiku-20241022"
|
|
42
|
-
):
|
|
37
|
+
async for chunk in backend.stream_with_tools(messages, [], model="claude-3-5-haiku-20241022"):
|
|
43
38
|
if chunk.type == "content":
|
|
44
39
|
content += chunk.content
|
|
45
40
|
print(chunk.content, end="", flush=True)
|
|
46
41
|
elif chunk.type == "complete_message":
|
|
47
|
-
print(
|
|
48
|
-
f"\n✅ Complete message received: {len(chunk.complete_message.get('content', ''))} chars"
|
|
49
|
-
)
|
|
42
|
+
print(f"\n✅ Complete message received: {len(chunk.complete_message.get('content', ''))} chars")
|
|
50
43
|
elif chunk.type == "done":
|
|
51
44
|
print("\n✅ Basic streaming test completed")
|
|
52
45
|
break
|
|
@@ -77,20 +70,18 @@ async def test_claude_tool_calling():
|
|
|
77
70
|
},
|
|
78
71
|
"required": ["width", "height"],
|
|
79
72
|
},
|
|
80
|
-
}
|
|
73
|
+
},
|
|
81
74
|
]
|
|
82
75
|
|
|
83
76
|
messages = [
|
|
84
77
|
{
|
|
85
78
|
"role": "user",
|
|
86
79
|
"content": "Calculate the area of a rectangle with width 5 and height 3.",
|
|
87
|
-
}
|
|
80
|
+
},
|
|
88
81
|
]
|
|
89
82
|
|
|
90
83
|
tool_calls_received = []
|
|
91
|
-
async for chunk in backend.stream_with_tools(
|
|
92
|
-
messages, tools, model="claude-3-5-haiku-20241022"
|
|
93
|
-
):
|
|
84
|
+
async for chunk in backend.stream_with_tools(messages, tools, model="claude-3-5-haiku-20241022"):
|
|
94
85
|
if chunk.type == "content":
|
|
95
86
|
print(chunk.content, end="", flush=True)
|
|
96
87
|
elif chunk.type == "tool_calls":
|
|
@@ -101,7 +92,7 @@ async def test_claude_tool_calling():
|
|
|
101
92
|
tool_args = backend.extract_tool_arguments(tool_call)
|
|
102
93
|
print(f" - {tool_name}: {tool_args}")
|
|
103
94
|
elif chunk.type == "complete_message":
|
|
104
|
-
print(
|
|
95
|
+
print("\n✅ Complete message with tool calls received")
|
|
105
96
|
elif chunk.type == "done":
|
|
106
97
|
print("✅ Tool calling test completed")
|
|
107
98
|
break
|
|
@@ -129,14 +120,14 @@ async def test_claude_multi_tool_support():
|
|
|
129
120
|
"properties": {"title": {"type": "string"}, "data": {"type": "string"}},
|
|
130
121
|
"required": ["title", "data"],
|
|
131
122
|
},
|
|
132
|
-
}
|
|
123
|
+
},
|
|
133
124
|
]
|
|
134
125
|
|
|
135
126
|
messages = [
|
|
136
127
|
{
|
|
137
128
|
"role": "user",
|
|
138
129
|
"content": "Search for recent news about AI and format the result with a nice title.",
|
|
139
|
-
}
|
|
130
|
+
},
|
|
140
131
|
]
|
|
141
132
|
|
|
142
133
|
# Enable both server-side tools and user tools
|
|
@@ -187,7 +178,7 @@ async def test_claude_message_conversion():
|
|
|
187
178
|
"id": "call_123",
|
|
188
179
|
"type": "function",
|
|
189
180
|
"function": {"name": "add", "arguments": {"a": 5, "b": 3}},
|
|
190
|
-
}
|
|
181
|
+
},
|
|
191
182
|
],
|
|
192
183
|
},
|
|
193
184
|
{"role": "tool", "tool_call_id": "call_123", "content": "8"},
|
|
@@ -203,11 +194,7 @@ async def test_claude_message_conversion():
|
|
|
203
194
|
# Check tool result conversion
|
|
204
195
|
tool_result_found = False
|
|
205
196
|
for msg in converted:
|
|
206
|
-
if (
|
|
207
|
-
msg.get("role") == "user"
|
|
208
|
-
and isinstance(msg.get("content"), list)
|
|
209
|
-
and any(item.get("type") == "tool_result" for item in msg["content"])
|
|
210
|
-
):
|
|
197
|
+
if msg.get("role") == "user" and isinstance(msg.get("content"), list) and any(item.get("type") == "tool_result" for item in msg["content"]):
|
|
211
198
|
tool_result_found = True
|
|
212
199
|
print(" ✅ Tool result conversion successful")
|
|
213
200
|
break
|
|
@@ -290,7 +277,7 @@ async def main():
|
|
|
290
277
|
results.append((test_name, False))
|
|
291
278
|
|
|
292
279
|
# Summary
|
|
293
|
-
print(
|
|
280
|
+
print("\n📊 Test Results Summary:")
|
|
294
281
|
passed = sum(1 for _, result in results if result)
|
|
295
282
|
total = len(results)
|
|
296
283
|
|
|
@@ -0,0 +1,268 @@
|
|
|
1
|
+
#!/usr/bin/env python3
|
|
2
|
+
# -*- coding: utf-8 -*-
|
|
3
|
+
"""
|
|
4
|
+
Real test of ClaudeCodeBackend with actual Claude Code API calls.
|
|
5
|
+
This test outputs the actual stream chunks to verify functionality.
|
|
6
|
+
"""
|
|
7
|
+
|
|
8
|
+
import asyncio
|
|
9
|
+
import os
|
|
10
|
+
|
|
11
|
+
from massgen.backend.claude_code import ClaudeCodeBackend
|
|
12
|
+
|
|
13
|
+
|
|
14
|
+
async def test_real_stream_with_tools():
|
|
15
|
+
"""Test real streaming with Claude Code API and output stream chunks."""
|
|
16
|
+
|
|
17
|
+
# Check if API key is available
|
|
18
|
+
if not os.getenv("ANTHROPIC_API_KEY"):
|
|
19
|
+
print("❌ ANTHROPIC_API_KEY not found in environment")
|
|
20
|
+
print("Set your API key: export ANTHROPIC_API_KEY=your-key-here")
|
|
21
|
+
return
|
|
22
|
+
|
|
23
|
+
print("🚀 Testing ClaudeCodeBackend with real Claude Code API")
|
|
24
|
+
print("=" * 60)
|
|
25
|
+
|
|
26
|
+
# Initialize backend
|
|
27
|
+
backend = ClaudeCodeBackend()
|
|
28
|
+
print(f"✅ Backend initialized: {backend.get_provider_name()}")
|
|
29
|
+
print(f"📊 Supported tools: {len(backend.get_supported_builtin_tools())} tools")
|
|
30
|
+
|
|
31
|
+
# Test single turn conversation
|
|
32
|
+
print("\n🔄 Testing single turn conversation...")
|
|
33
|
+
messages = [
|
|
34
|
+
{
|
|
35
|
+
"role": "user",
|
|
36
|
+
"content": "Hello! Can you tell me what 2+2 equals and show your calculation?",
|
|
37
|
+
},
|
|
38
|
+
]
|
|
39
|
+
|
|
40
|
+
try:
|
|
41
|
+
print("\n📨 Sending messages:", messages)
|
|
42
|
+
print("\n📡 Stream chunks received:")
|
|
43
|
+
print("-" * 40)
|
|
44
|
+
|
|
45
|
+
chunk_count = 0
|
|
46
|
+
total_content = ""
|
|
47
|
+
|
|
48
|
+
async for chunk in backend.stream_with_tools(messages, []):
|
|
49
|
+
chunk_count += 1
|
|
50
|
+
print(f"[{chunk_count:2d}] Type: {chunk.type:<20} Source: {chunk.source or 'None':<20}")
|
|
51
|
+
|
|
52
|
+
if chunk.type == "content":
|
|
53
|
+
print(f" Content: {repr(chunk.content)}")
|
|
54
|
+
total_content += chunk.content or ""
|
|
55
|
+
elif chunk.type == "complete_message":
|
|
56
|
+
print(f" Complete message: {chunk.complete_message}")
|
|
57
|
+
elif chunk.type == "complete_response":
|
|
58
|
+
print(f" Response metadata: {chunk.response}")
|
|
59
|
+
elif chunk.type == "agent_status":
|
|
60
|
+
print(f" Status: {chunk.status} - {chunk.content}")
|
|
61
|
+
elif chunk.type == "builtin_tool_results":
|
|
62
|
+
print(f" Tool results: {chunk.builtin_tool_results}")
|
|
63
|
+
elif chunk.type == "tool_calls":
|
|
64
|
+
print(f" Tool calls: {chunk.tool_calls}")
|
|
65
|
+
elif chunk.type == "error":
|
|
66
|
+
print(f" Error: {chunk.error}")
|
|
67
|
+
elif chunk.type == "done":
|
|
68
|
+
print(" ✅ Stream completed")
|
|
69
|
+
break
|
|
70
|
+
|
|
71
|
+
print()
|
|
72
|
+
|
|
73
|
+
print("-" * 40)
|
|
74
|
+
print(f"📊 Total chunks: {chunk_count}")
|
|
75
|
+
print(f"📝 Total content length: {len(total_content)} chars")
|
|
76
|
+
print(f"💰 Token usage: {backend.get_token_usage()}")
|
|
77
|
+
print(f"🔗 Session ID: {backend.get_current_session_id()}")
|
|
78
|
+
|
|
79
|
+
if total_content:
|
|
80
|
+
print(f"\n📄 Complete response:\n{total_content}")
|
|
81
|
+
|
|
82
|
+
except Exception as e:
|
|
83
|
+
print(f"❌ Error during streaming: {e}")
|
|
84
|
+
import traceback
|
|
85
|
+
|
|
86
|
+
traceback.print_exc()
|
|
87
|
+
return
|
|
88
|
+
|
|
89
|
+
# Test multi-turn conversation
|
|
90
|
+
print("\n" + "=" * 60)
|
|
91
|
+
print("🔄 Testing multi-turn conversation...")
|
|
92
|
+
|
|
93
|
+
# Add assistant response to conversation
|
|
94
|
+
messages.append({"role": "assistant", "content": total_content})
|
|
95
|
+
|
|
96
|
+
# Add follow-up question
|
|
97
|
+
messages.append(
|
|
98
|
+
{
|
|
99
|
+
"role": "user",
|
|
100
|
+
"content": "Great! Now can you show me how to calculate the result times 5?",
|
|
101
|
+
},
|
|
102
|
+
)
|
|
103
|
+
|
|
104
|
+
try:
|
|
105
|
+
print("\n📨 Sending multi-turn messages:")
|
|
106
|
+
for i, msg in enumerate(messages):
|
|
107
|
+
print(f" [{i+1}] {msg['role']}: {msg['content'][:100]}{'...' if len(msg['content']) > 100 else ''}")
|
|
108
|
+
|
|
109
|
+
print("\n📡 Stream chunks received:")
|
|
110
|
+
print("-" * 40)
|
|
111
|
+
|
|
112
|
+
chunk_count = 0
|
|
113
|
+
turn2_content = ""
|
|
114
|
+
|
|
115
|
+
async for chunk in backend.stream_with_tools(messages, []):
|
|
116
|
+
chunk_count += 1
|
|
117
|
+
print(f"[{chunk_count:2d}] Type: {chunk.type:<20} Source: {chunk.source or 'None':<20}")
|
|
118
|
+
|
|
119
|
+
if chunk.type == "content":
|
|
120
|
+
print(f" Content: {repr(chunk.content)}")
|
|
121
|
+
turn2_content += chunk.content or ""
|
|
122
|
+
elif chunk.type == "complete_response":
|
|
123
|
+
print(f" Response metadata: {chunk.response}")
|
|
124
|
+
elif chunk.type == "done":
|
|
125
|
+
print(" ✅ Stream completed")
|
|
126
|
+
break
|
|
127
|
+
|
|
128
|
+
print()
|
|
129
|
+
|
|
130
|
+
print("-" * 40)
|
|
131
|
+
print(f"📊 Turn 2 chunks: {chunk_count}")
|
|
132
|
+
print(f"📝 Turn 2 content length: {len(turn2_content)} chars")
|
|
133
|
+
print(f"💰 Cumulative token usage: {backend.get_token_usage()}")
|
|
134
|
+
print(f"🔗 Session ID: {backend.get_current_session_id()}")
|
|
135
|
+
|
|
136
|
+
if turn2_content:
|
|
137
|
+
print(f"\n📄 Turn 2 response:\n{turn2_content}")
|
|
138
|
+
|
|
139
|
+
except Exception as e:
|
|
140
|
+
print(f"❌ Error during multi-turn: {e}")
|
|
141
|
+
import traceback
|
|
142
|
+
|
|
143
|
+
traceback.print_exc()
|
|
144
|
+
return
|
|
145
|
+
|
|
146
|
+
print("\n✅ Multi-turn conversation test completed successfully!")
|
|
147
|
+
|
|
148
|
+
|
|
149
|
+
async def test_with_workflow_tools():
|
|
150
|
+
"""Test with MassGen workflow tools."""
|
|
151
|
+
|
|
152
|
+
print("\n" + "=" * 60)
|
|
153
|
+
print("🛠️ Testing with workflow tools...")
|
|
154
|
+
|
|
155
|
+
backend = ClaudeCodeBackend()
|
|
156
|
+
|
|
157
|
+
# Define workflow tools
|
|
158
|
+
workflow_tools = [
|
|
159
|
+
{
|
|
160
|
+
"type": "function",
|
|
161
|
+
"function": {
|
|
162
|
+
"name": "new_answer",
|
|
163
|
+
"description": "Provide an improved answer to the ORIGINAL MESSAGE",
|
|
164
|
+
"parameters": {
|
|
165
|
+
"type": "object",
|
|
166
|
+
"properties": {
|
|
167
|
+
"content": {
|
|
168
|
+
"type": "string",
|
|
169
|
+
"description": "Your improved answer",
|
|
170
|
+
},
|
|
171
|
+
},
|
|
172
|
+
"required": ["content"],
|
|
173
|
+
},
|
|
174
|
+
},
|
|
175
|
+
},
|
|
176
|
+
{
|
|
177
|
+
"type": "function",
|
|
178
|
+
"function": {
|
|
179
|
+
"name": "vote",
|
|
180
|
+
"description": "Vote for the best agent to present final answer",
|
|
181
|
+
"parameters": {
|
|
182
|
+
"type": "object",
|
|
183
|
+
"properties": {
|
|
184
|
+
"agent_id": {
|
|
185
|
+
"type": "string",
|
|
186
|
+
"description": "Agent ID to vote for",
|
|
187
|
+
},
|
|
188
|
+
"reason": {
|
|
189
|
+
"type": "string",
|
|
190
|
+
"description": "Reason for voting",
|
|
191
|
+
},
|
|
192
|
+
},
|
|
193
|
+
"required": ["agent_id", "reason"],
|
|
194
|
+
},
|
|
195
|
+
},
|
|
196
|
+
},
|
|
197
|
+
]
|
|
198
|
+
|
|
199
|
+
messages = [
|
|
200
|
+
{
|
|
201
|
+
"role": "user",
|
|
202
|
+
"content": "You are participating in a multi-agent workflow. Please provide an answer about the benefits of Python programming, then use the new_answer tool to submit your response.",
|
|
203
|
+
},
|
|
204
|
+
]
|
|
205
|
+
|
|
206
|
+
try:
|
|
207
|
+
print(f"\n📨 Sending workflow tool message with {len(workflow_tools)} tools")
|
|
208
|
+
print(f"🛠️ Tools: {[t['function']['name'] for t in workflow_tools]}")
|
|
209
|
+
|
|
210
|
+
print("\n📡 Stream chunks received:")
|
|
211
|
+
print("-" * 40)
|
|
212
|
+
|
|
213
|
+
chunk_count = 0
|
|
214
|
+
workflow_content = ""
|
|
215
|
+
detected_tool_calls = []
|
|
216
|
+
|
|
217
|
+
async for chunk in backend.stream_with_tools(messages, workflow_tools):
|
|
218
|
+
chunk_count += 1
|
|
219
|
+
print(f"[{chunk_count:2d}] Type: {chunk.type:<20} Source: {chunk.source or 'None':<20}")
|
|
220
|
+
|
|
221
|
+
if chunk.type == "content":
|
|
222
|
+
print(f" Content: {repr(chunk.content)}")
|
|
223
|
+
workflow_content += chunk.content or ""
|
|
224
|
+
elif chunk.type == "tool_calls":
|
|
225
|
+
print(f" 🛠️ Tool calls detected: {chunk.tool_calls}")
|
|
226
|
+
detected_tool_calls.extend(chunk.tool_calls or [])
|
|
227
|
+
elif chunk.type == "complete_response":
|
|
228
|
+
print(f" Response metadata: {chunk.response}")
|
|
229
|
+
elif chunk.type == "done":
|
|
230
|
+
print(" ✅ Stream completed")
|
|
231
|
+
break
|
|
232
|
+
|
|
233
|
+
print()
|
|
234
|
+
|
|
235
|
+
print("-" * 40)
|
|
236
|
+
print(f"📊 Workflow chunks: {chunk_count}")
|
|
237
|
+
print(f"📝 Workflow content length: {len(workflow_content)} chars")
|
|
238
|
+
print(f"🛠️ Detected tool calls: {len(detected_tool_calls)}")
|
|
239
|
+
for i, tool_call in enumerate(detected_tool_calls):
|
|
240
|
+
print(f" [{i+1}] {tool_call.get('function', {}).get('name', 'unknown')}: {tool_call}")
|
|
241
|
+
print(f"💰 Token usage: {backend.get_token_usage()}")
|
|
242
|
+
|
|
243
|
+
if workflow_content:
|
|
244
|
+
print(f"\n📄 Workflow response:\n{workflow_content}")
|
|
245
|
+
|
|
246
|
+
except Exception as e:
|
|
247
|
+
print(f"❌ Error during workflow test: {e}")
|
|
248
|
+
import traceback
|
|
249
|
+
|
|
250
|
+
traceback.print_exc()
|
|
251
|
+
return
|
|
252
|
+
|
|
253
|
+
print("\n✅ Workflow tools test completed!")
|
|
254
|
+
|
|
255
|
+
|
|
256
|
+
async def main():
|
|
257
|
+
"""Run all real tests."""
|
|
258
|
+
print("🧪 ClaudeCodeBackend Real API Tests")
|
|
259
|
+
print("=" * 60)
|
|
260
|
+
|
|
261
|
+
await test_real_stream_with_tools()
|
|
262
|
+
await test_with_workflow_tools()
|
|
263
|
+
|
|
264
|
+
print("\n🎉 All tests completed!")
|
|
265
|
+
|
|
266
|
+
|
|
267
|
+
if __name__ == "__main__":
|
|
268
|
+
asyncio.run(main())
|