massgen 0.0.3__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 +94 -0
- massgen/agent_config.py +507 -0
- massgen/backend/CLAUDE_API_RESEARCH.md +266 -0
- massgen/backend/Function calling openai responses.md +1161 -0
- massgen/backend/GEMINI_API_DOCUMENTATION.md +410 -0
- massgen/backend/OPENAI_RESPONSES_API_FORMAT.md +65 -0
- massgen/backend/__init__.py +25 -0
- massgen/backend/base.py +180 -0
- massgen/backend/chat_completions.py +228 -0
- massgen/backend/claude.py +661 -0
- massgen/backend/gemini.py +652 -0
- massgen/backend/grok.py +187 -0
- massgen/backend/response.py +397 -0
- massgen/chat_agent.py +440 -0
- massgen/cli.py +686 -0
- massgen/configs/README.md +293 -0
- massgen/configs/creative_team.yaml +53 -0
- massgen/configs/gemini_4o_claude.yaml +31 -0
- massgen/configs/news_analysis.yaml +51 -0
- massgen/configs/research_team.yaml +51 -0
- massgen/configs/single_agent.yaml +18 -0
- massgen/configs/single_flash2.5.yaml +44 -0
- massgen/configs/technical_analysis.yaml +51 -0
- massgen/configs/three_agents_default.yaml +31 -0
- massgen/configs/travel_planning.yaml +51 -0
- massgen/configs/two_agents.yaml +39 -0
- massgen/frontend/__init__.py +20 -0
- massgen/frontend/coordination_ui.py +945 -0
- massgen/frontend/displays/__init__.py +24 -0
- massgen/frontend/displays/base_display.py +83 -0
- massgen/frontend/displays/rich_terminal_display.py +3497 -0
- massgen/frontend/displays/simple_display.py +93 -0
- massgen/frontend/displays/terminal_display.py +381 -0
- massgen/frontend/logging/__init__.py +9 -0
- massgen/frontend/logging/realtime_logger.py +197 -0
- massgen/message_templates.py +431 -0
- massgen/orchestrator.py +1222 -0
- massgen/tests/__init__.py +10 -0
- massgen/tests/multi_turn_conversation_design.md +214 -0
- massgen/tests/multiturn_llm_input_analysis.md +189 -0
- massgen/tests/test_case_studies.md +113 -0
- massgen/tests/test_claude_backend.py +310 -0
- massgen/tests/test_grok_backend.py +160 -0
- massgen/tests/test_message_context_building.py +293 -0
- massgen/tests/test_rich_terminal_display.py +378 -0
- massgen/tests/test_v3_3agents.py +117 -0
- massgen/tests/test_v3_simple.py +216 -0
- massgen/tests/test_v3_three_agents.py +272 -0
- massgen/tests/test_v3_two_agents.py +176 -0
- massgen/utils.py +79 -0
- massgen/v1/README.md +330 -0
- massgen/v1/__init__.py +91 -0
- massgen/v1/agent.py +605 -0
- massgen/v1/agents.py +330 -0
- massgen/v1/backends/gemini.py +584 -0
- massgen/v1/backends/grok.py +410 -0
- massgen/v1/backends/oai.py +571 -0
- massgen/v1/cli.py +351 -0
- massgen/v1/config.py +169 -0
- massgen/v1/examples/fast-4o-mini-config.yaml +44 -0
- massgen/v1/examples/fast_config.yaml +44 -0
- massgen/v1/examples/production.yaml +70 -0
- massgen/v1/examples/single_agent.yaml +39 -0
- massgen/v1/logging.py +974 -0
- massgen/v1/main.py +368 -0
- massgen/v1/orchestrator.py +1138 -0
- massgen/v1/streaming_display.py +1190 -0
- massgen/v1/tools.py +160 -0
- massgen/v1/types.py +245 -0
- massgen/v1/utils.py +199 -0
- massgen-0.0.3.dist-info/METADATA +568 -0
- massgen-0.0.3.dist-info/RECORD +76 -0
- massgen-0.0.3.dist-info/WHEEL +5 -0
- massgen-0.0.3.dist-info/entry_points.txt +2 -0
- massgen-0.0.3.dist-info/licenses/LICENSE +204 -0
- massgen-0.0.3.dist-info/top_level.txt +1 -0
|
@@ -0,0 +1,293 @@
|
|
|
1
|
+
#!/usr/bin/env python3
|
|
2
|
+
"""
|
|
3
|
+
Test script to examine how conversation context is built for LLM input.
|
|
4
|
+
Shows the exact message templates and context structure without making API calls.
|
|
5
|
+
"""
|
|
6
|
+
|
|
7
|
+
import sys
|
|
8
|
+
from pathlib import Path
|
|
9
|
+
from typing import Dict, List, Any
|
|
10
|
+
|
|
11
|
+
# Add project root to path
|
|
12
|
+
project_root = Path(__file__).parent.parent.parent.parent
|
|
13
|
+
sys.path.insert(0, str(project_root))
|
|
14
|
+
|
|
15
|
+
from massgen.message_templates import MessageTemplates
|
|
16
|
+
|
|
17
|
+
|
|
18
|
+
def print_message_structure(title: str, conversation: Dict[str, Any]):
|
|
19
|
+
"""Print the structure of a conversation message in a readable format."""
|
|
20
|
+
print(f"\n{'='*80}")
|
|
21
|
+
print(f"š {title}")
|
|
22
|
+
print(f"{'='*80}")
|
|
23
|
+
|
|
24
|
+
# System message
|
|
25
|
+
print("š SYSTEM MESSAGE:")
|
|
26
|
+
print("-" * 40)
|
|
27
|
+
system_msg = conversation["system_message"]
|
|
28
|
+
print(system_msg)
|
|
29
|
+
|
|
30
|
+
# User message
|
|
31
|
+
print(f"\nšØ USER MESSAGE:")
|
|
32
|
+
print("-" * 40)
|
|
33
|
+
user_msg = conversation["user_message"]
|
|
34
|
+
print(user_msg)
|
|
35
|
+
|
|
36
|
+
# Tools
|
|
37
|
+
print(f"\nš§ TOOLS PROVIDED:")
|
|
38
|
+
print("-" * 40)
|
|
39
|
+
tools = conversation.get("tools", [])
|
|
40
|
+
for i, tool in enumerate(tools, 1):
|
|
41
|
+
tool_name = tool.get("function", {}).get("name", "unknown")
|
|
42
|
+
tool_desc = tool.get("function", {}).get("description", "No description")
|
|
43
|
+
print(f"{i}. {tool_name}: {tool_desc}")
|
|
44
|
+
|
|
45
|
+
print(f"\nš STATISTICS:")
|
|
46
|
+
print(f" System message length: {len(system_msg)} chars")
|
|
47
|
+
print(f" User message length: {len(user_msg)} chars")
|
|
48
|
+
print(f" Tools provided: {len(tools)}")
|
|
49
|
+
print(f" Total context size: {len(system_msg) + len(user_msg)} chars")
|
|
50
|
+
|
|
51
|
+
|
|
52
|
+
def test_turn1_context():
|
|
53
|
+
"""Test context building for the first turn (no history)."""
|
|
54
|
+
print("š· TURN 1 CONTEXT BUILDING")
|
|
55
|
+
print("Scenario: User asks initial question, no conversation history")
|
|
56
|
+
|
|
57
|
+
templates = MessageTemplates()
|
|
58
|
+
|
|
59
|
+
# Build conversation for first turn
|
|
60
|
+
conversation = templates.build_conversation_with_context(
|
|
61
|
+
current_task="What are the main benefits of renewable energy?",
|
|
62
|
+
conversation_history=[], # No history on first turn
|
|
63
|
+
agent_summaries=None, # No agent answers yet
|
|
64
|
+
valid_agent_ids=None,
|
|
65
|
+
)
|
|
66
|
+
|
|
67
|
+
print_message_structure("Turn 1: Initial Question", conversation)
|
|
68
|
+
|
|
69
|
+
# Verify structure
|
|
70
|
+
user_msg = conversation["user_message"]
|
|
71
|
+
has_history = "CONVERSATION_HISTORY" in user_msg
|
|
72
|
+
has_original = "ORIGINAL MESSAGE" in user_msg
|
|
73
|
+
has_answers = (
|
|
74
|
+
"CURRENT ANSWERS" in user_msg and "no answers available yet" in user_msg
|
|
75
|
+
)
|
|
76
|
+
|
|
77
|
+
print(f"\nā
VALIDATION:")
|
|
78
|
+
print(f" Contains conversation history section: {has_history}")
|
|
79
|
+
print(f" Contains original message section: {has_original}")
|
|
80
|
+
print(f" Contains empty answers section: {has_answers}")
|
|
81
|
+
print(
|
|
82
|
+
f" System message mentions context: {'conversation' in conversation['system_message'].lower()}"
|
|
83
|
+
)
|
|
84
|
+
|
|
85
|
+
|
|
86
|
+
def test_turn2_context():
|
|
87
|
+
"""Test context building for the second turn (with history)."""
|
|
88
|
+
print(f"\nš· TURN 2 CONTEXT BUILDING")
|
|
89
|
+
print("Scenario: User asks follow-up, with previous exchange in history")
|
|
90
|
+
|
|
91
|
+
templates = MessageTemplates()
|
|
92
|
+
|
|
93
|
+
# Simulate conversation history from Turn 1
|
|
94
|
+
conversation_history = [
|
|
95
|
+
{"role": "user", "content": "What are the main benefits of renewable energy?"},
|
|
96
|
+
{
|
|
97
|
+
"role": "assistant",
|
|
98
|
+
"content": "Renewable energy offers several key benefits including environmental sustainability, economic advantages, and energy security. It reduces greenhouse gas emissions, creates jobs, and decreases dependence on fossil fuel imports.",
|
|
99
|
+
},
|
|
100
|
+
]
|
|
101
|
+
|
|
102
|
+
# Build conversation for second turn with history
|
|
103
|
+
conversation = templates.build_conversation_with_context(
|
|
104
|
+
current_task="What about the challenges and limitations?",
|
|
105
|
+
conversation_history=conversation_history,
|
|
106
|
+
agent_summaries={
|
|
107
|
+
"researcher": "Key benefits include environmental and economic advantages."
|
|
108
|
+
},
|
|
109
|
+
valid_agent_ids=["researcher"],
|
|
110
|
+
)
|
|
111
|
+
|
|
112
|
+
print_message_structure("Turn 2: Follow-up with History", conversation)
|
|
113
|
+
|
|
114
|
+
# Verify structure
|
|
115
|
+
user_msg = conversation["user_message"]
|
|
116
|
+
has_history = (
|
|
117
|
+
"CONVERSATION_HISTORY" in user_msg
|
|
118
|
+
and "User: What are the main benefits" in user_msg
|
|
119
|
+
)
|
|
120
|
+
has_original = (
|
|
121
|
+
"ORIGINAL MESSAGE" in user_msg and "challenges and limitations" in user_msg
|
|
122
|
+
)
|
|
123
|
+
has_answers = "CURRENT ANSWERS" in user_msg and "researcher" in user_msg
|
|
124
|
+
|
|
125
|
+
print(f"\nā
VALIDATION:")
|
|
126
|
+
print(f" Contains conversation history: {has_history}")
|
|
127
|
+
print(f" Contains current question: {has_original}")
|
|
128
|
+
print(f" Contains agent answers: {has_answers}")
|
|
129
|
+
print(
|
|
130
|
+
f" System message is context-aware: {'conversation' in conversation['system_message'].lower()}"
|
|
131
|
+
)
|
|
132
|
+
|
|
133
|
+
|
|
134
|
+
def test_turn3_context():
|
|
135
|
+
"""Test context building for the third turn (extended history)."""
|
|
136
|
+
print(f"\nš· TURN 3 CONTEXT BUILDING")
|
|
137
|
+
print("Scenario: User asks third question, with extended conversation history")
|
|
138
|
+
|
|
139
|
+
templates = MessageTemplates()
|
|
140
|
+
|
|
141
|
+
# Simulate extended conversation history
|
|
142
|
+
conversation_history = [
|
|
143
|
+
{"role": "user", "content": "What are the main benefits of renewable energy?"},
|
|
144
|
+
{
|
|
145
|
+
"role": "assistant",
|
|
146
|
+
"content": "Renewable energy offers environmental, economic, and energy security benefits.",
|
|
147
|
+
},
|
|
148
|
+
{"role": "user", "content": "What about the challenges and limitations?"},
|
|
149
|
+
{
|
|
150
|
+
"role": "assistant",
|
|
151
|
+
"content": "Main challenges include high upfront costs, intermittency issues, and infrastructure requirements.",
|
|
152
|
+
},
|
|
153
|
+
]
|
|
154
|
+
|
|
155
|
+
# Build conversation for third turn with extended history
|
|
156
|
+
conversation = templates.build_conversation_with_context(
|
|
157
|
+
current_task="How can governments support the transition?",
|
|
158
|
+
conversation_history=conversation_history,
|
|
159
|
+
agent_summaries={
|
|
160
|
+
"researcher": "Benefits include environmental and economic advantages.",
|
|
161
|
+
"analyst": "Challenges include costs, intermittency, and infrastructure needs.",
|
|
162
|
+
},
|
|
163
|
+
valid_agent_ids=["researcher", "analyst"],
|
|
164
|
+
)
|
|
165
|
+
|
|
166
|
+
print_message_structure("Turn 3: Extended Conversation", conversation)
|
|
167
|
+
|
|
168
|
+
# Verify structure
|
|
169
|
+
user_msg = conversation["user_message"]
|
|
170
|
+
has_full_history = (
|
|
171
|
+
"CONVERSATION_HISTORY" in user_msg and user_msg.count("User:") >= 2
|
|
172
|
+
)
|
|
173
|
+
has_original = "ORIGINAL MESSAGE" in user_msg and "governments support" in user_msg
|
|
174
|
+
has_multiple_answers = (
|
|
175
|
+
"CURRENT ANSWERS" in user_msg
|
|
176
|
+
and "researcher" in user_msg
|
|
177
|
+
and "analyst" in user_msg
|
|
178
|
+
)
|
|
179
|
+
|
|
180
|
+
print(f"\nā
VALIDATION:")
|
|
181
|
+
print(f" Contains full conversation history: {has_full_history}")
|
|
182
|
+
print(f" Contains current question: {has_original}")
|
|
183
|
+
print(f" Contains multiple agent answers: {has_multiple_answers}")
|
|
184
|
+
print(f" History shows progression: {user_msg.count('User:') >= 2}")
|
|
185
|
+
|
|
186
|
+
|
|
187
|
+
def test_context_comparison():
|
|
188
|
+
"""Compare context building across different turns."""
|
|
189
|
+
print(f"\nš CONTEXT COMPARISON ACROSS TURNS")
|
|
190
|
+
print("=" * 80)
|
|
191
|
+
|
|
192
|
+
templates = MessageTemplates()
|
|
193
|
+
|
|
194
|
+
# Turn 1: No history
|
|
195
|
+
conv1 = templates.build_conversation_with_context(
|
|
196
|
+
current_task="What is solar energy?",
|
|
197
|
+
conversation_history=[],
|
|
198
|
+
agent_summaries=None,
|
|
199
|
+
)
|
|
200
|
+
|
|
201
|
+
# Turn 2: With history
|
|
202
|
+
history = [
|
|
203
|
+
{"role": "user", "content": "What is solar energy?"},
|
|
204
|
+
{
|
|
205
|
+
"role": "assistant",
|
|
206
|
+
"content": "Solar energy is power derived from sunlight.",
|
|
207
|
+
},
|
|
208
|
+
]
|
|
209
|
+
conv2 = templates.build_conversation_with_context(
|
|
210
|
+
current_task="How efficient is it?",
|
|
211
|
+
conversation_history=history,
|
|
212
|
+
agent_summaries={
|
|
213
|
+
"expert": "Solar energy harnesses sunlight for power generation."
|
|
214
|
+
},
|
|
215
|
+
)
|
|
216
|
+
|
|
217
|
+
# Turn 3: Extended history
|
|
218
|
+
extended_history = [
|
|
219
|
+
{"role": "user", "content": "What is solar energy?"},
|
|
220
|
+
{
|
|
221
|
+
"role": "assistant",
|
|
222
|
+
"content": "Solar energy is power derived from sunlight.",
|
|
223
|
+
},
|
|
224
|
+
{"role": "user", "content": "How efficient is it?"},
|
|
225
|
+
{
|
|
226
|
+
"role": "assistant",
|
|
227
|
+
"content": "Modern solar panels achieve 15-22% efficiency.",
|
|
228
|
+
},
|
|
229
|
+
]
|
|
230
|
+
conv3 = templates.build_conversation_with_context(
|
|
231
|
+
current_task="What are the costs?",
|
|
232
|
+
conversation_history=extended_history,
|
|
233
|
+
agent_summaries={
|
|
234
|
+
"expert": "Solar energy harnesses sunlight for power generation.",
|
|
235
|
+
"engineer": "Modern panels achieve 15-22% efficiency.",
|
|
236
|
+
},
|
|
237
|
+
)
|
|
238
|
+
|
|
239
|
+
print("š CONTEXT SIZE PROGRESSION:")
|
|
240
|
+
print(f" Turn 1 (no history): {len(conv1['user_message']):,} chars")
|
|
241
|
+
print(f" Turn 2 (with history): {len(conv2['user_message']):,} chars")
|
|
242
|
+
print(f" Turn 3 (extended): {len(conv3['user_message']):,} chars")
|
|
243
|
+
|
|
244
|
+
print(f"\nš CONTEXT ELEMENTS:")
|
|
245
|
+
elements = ["CONVERSATION_HISTORY", "ORIGINAL MESSAGE", "CURRENT ANSWERS"]
|
|
246
|
+
|
|
247
|
+
for i, (conv, turn) in enumerate(
|
|
248
|
+
[(conv1, "Turn 1"), (conv2, "Turn 2"), (conv3, "Turn 3")], 1
|
|
249
|
+
):
|
|
250
|
+
user_msg = conv["user_message"]
|
|
251
|
+
print(f"\n {turn}:")
|
|
252
|
+
for element in elements:
|
|
253
|
+
present = element in user_msg
|
|
254
|
+
print(f" {element}: {'ā
' if present else 'ā'}")
|
|
255
|
+
|
|
256
|
+
# Count conversation exchanges
|
|
257
|
+
if "CONVERSATION_HISTORY" in user_msg:
|
|
258
|
+
exchange_count = user_msg.count("User:")
|
|
259
|
+
print(f" Previous exchanges: {exchange_count}")
|
|
260
|
+
|
|
261
|
+
|
|
262
|
+
def main():
|
|
263
|
+
"""Run all context building tests."""
|
|
264
|
+
print("š MassGen - Message Context Building Analysis")
|
|
265
|
+
print("=" * 80)
|
|
266
|
+
print("This test examines how conversation context is structured")
|
|
267
|
+
print("for LLM input across multiple conversation turns.")
|
|
268
|
+
print()
|
|
269
|
+
|
|
270
|
+
try:
|
|
271
|
+
# Test each turn's context building
|
|
272
|
+
test_turn1_context()
|
|
273
|
+
test_turn2_context()
|
|
274
|
+
test_turn3_context()
|
|
275
|
+
test_context_comparison()
|
|
276
|
+
|
|
277
|
+
print(f"\nš ALL CONTEXT BUILDING TESTS COMPLETED")
|
|
278
|
+
print("=" * 80)
|
|
279
|
+
print("ā
Message templates properly build conversation context")
|
|
280
|
+
print("ā
Context grows appropriately with conversation history")
|
|
281
|
+
print("ā
All required sections are included in each turn")
|
|
282
|
+
print("š Review the detailed context structures above to understand")
|
|
283
|
+
print(" exactly what information is provided to agents at each turn.")
|
|
284
|
+
|
|
285
|
+
except Exception as e:
|
|
286
|
+
print(f"ā Context building test failed: {e}")
|
|
287
|
+
import traceback
|
|
288
|
+
|
|
289
|
+
traceback.print_exc()
|
|
290
|
+
|
|
291
|
+
|
|
292
|
+
if __name__ == "__main__":
|
|
293
|
+
main()
|
|
@@ -0,0 +1,378 @@
|
|
|
1
|
+
#!/usr/bin/env python3
|
|
2
|
+
"""
|
|
3
|
+
Test script for MassGen Rich Terminal Display.
|
|
4
|
+
Tests RichTerminalDisplay functionality with two-agent coordination.
|
|
5
|
+
"""
|
|
6
|
+
|
|
7
|
+
import asyncio
|
|
8
|
+
import os
|
|
9
|
+
import sys
|
|
10
|
+
from pathlib import Path
|
|
11
|
+
|
|
12
|
+
# Add project root to path
|
|
13
|
+
project_root = Path(__file__).parent.parent.parent
|
|
14
|
+
sys.path.insert(0, str(project_root))
|
|
15
|
+
|
|
16
|
+
from massgen.backend.response import ResponseBackend
|
|
17
|
+
from massgen.chat_agent import SingleAgent
|
|
18
|
+
from massgen.orchestrator import Orchestrator
|
|
19
|
+
from massgen.frontend.coordination_ui import CoordinationUI, coordinate_with_rich_ui
|
|
20
|
+
from massgen.frontend.displays.rich_terminal_display import is_rich_available
|
|
21
|
+
|
|
22
|
+
|
|
23
|
+
async def test_rich_availability():
|
|
24
|
+
"""Test Rich library availability and display info."""
|
|
25
|
+
print("šØ Rich Library Availability Test")
|
|
26
|
+
print("-" * 40)
|
|
27
|
+
|
|
28
|
+
if is_rich_available():
|
|
29
|
+
print("ā
Rich library is available")
|
|
30
|
+
try:
|
|
31
|
+
from rich import __version__
|
|
32
|
+
|
|
33
|
+
print(f"š¦ Rich version: {__version__}")
|
|
34
|
+
except ImportError:
|
|
35
|
+
print("š¦ Rich version: Unknown")
|
|
36
|
+
return True
|
|
37
|
+
else:
|
|
38
|
+
print("ā Rich library is not available")
|
|
39
|
+
print("š” Install with: pip install rich")
|
|
40
|
+
return False
|
|
41
|
+
|
|
42
|
+
|
|
43
|
+
async def test_rich_display_basic():
|
|
44
|
+
"""Test basic RichTerminalDisplay creation and configuration."""
|
|
45
|
+
print("\nš„ļø Rich Display Basic Test")
|
|
46
|
+
print("-" * 40)
|
|
47
|
+
|
|
48
|
+
if not is_rich_available():
|
|
49
|
+
print("ā ļø Skipping - Rich library not available")
|
|
50
|
+
return False
|
|
51
|
+
|
|
52
|
+
try:
|
|
53
|
+
from massgen.frontend.displays.rich_terminal_display import RichTerminalDisplay
|
|
54
|
+
|
|
55
|
+
# Test basic creation
|
|
56
|
+
agent_ids = ["agent1", "agent2"]
|
|
57
|
+
display = RichTerminalDisplay(agent_ids)
|
|
58
|
+
|
|
59
|
+
print("ā
RichTerminalDisplay created successfully")
|
|
60
|
+
print(f"š Agent IDs: {display.agent_ids}")
|
|
61
|
+
print(f"šØ Theme: {display.theme}")
|
|
62
|
+
print(f"š Refresh rate: {display.refresh_rate} Hz")
|
|
63
|
+
|
|
64
|
+
# Test theme configuration
|
|
65
|
+
themes = ["dark", "light", "cyberpunk"]
|
|
66
|
+
for theme in themes:
|
|
67
|
+
themed_display = RichTerminalDisplay(agent_ids, theme=theme)
|
|
68
|
+
print(f"ā
{theme.title()} theme created successfully")
|
|
69
|
+
|
|
70
|
+
# Clean up
|
|
71
|
+
display.cleanup()
|
|
72
|
+
|
|
73
|
+
return True
|
|
74
|
+
|
|
75
|
+
except Exception as e:
|
|
76
|
+
print(f"ā Rich display basic test failed: {e}")
|
|
77
|
+
import traceback
|
|
78
|
+
|
|
79
|
+
traceback.print_exc()
|
|
80
|
+
return False
|
|
81
|
+
|
|
82
|
+
|
|
83
|
+
async def test_rich_display_coordination():
|
|
84
|
+
"""Test RichTerminalDisplay with actual agent coordination."""
|
|
85
|
+
print("\nš¤ Rich Display Coordination Test")
|
|
86
|
+
print("-" * 40)
|
|
87
|
+
|
|
88
|
+
if not is_rich_available():
|
|
89
|
+
print("ā ļø Skipping - Rich library not available")
|
|
90
|
+
return False
|
|
91
|
+
|
|
92
|
+
api_key = os.getenv("OPENAI_API_KEY")
|
|
93
|
+
if not api_key:
|
|
94
|
+
print("ā OPENAI_API_KEY not found - skipping coordination test")
|
|
95
|
+
return False
|
|
96
|
+
|
|
97
|
+
try:
|
|
98
|
+
# Create backend
|
|
99
|
+
backend = ResponseBackend(api_key=api_key)
|
|
100
|
+
|
|
101
|
+
# Create two agents for rich display testing
|
|
102
|
+
creative_agent = SingleAgent(
|
|
103
|
+
backend=backend,
|
|
104
|
+
agent_id="creative",
|
|
105
|
+
system_message="You are a creative writer who crafts engaging and imaginative responses. Focus on storytelling and creative expression.",
|
|
106
|
+
)
|
|
107
|
+
|
|
108
|
+
technical_agent = SingleAgent(
|
|
109
|
+
backend=backend,
|
|
110
|
+
agent_id="technical",
|
|
111
|
+
system_message="You are a technical expert who provides precise and detailed technical information. Focus on accuracy and technical depth.",
|
|
112
|
+
)
|
|
113
|
+
|
|
114
|
+
# Create orchestrator
|
|
115
|
+
agents = {"creative": creative_agent, "technical": technical_agent}
|
|
116
|
+
|
|
117
|
+
orchestrator = Orchestrator(agents=agents)
|
|
118
|
+
|
|
119
|
+
# Test with Rich UI using cyberpunk theme
|
|
120
|
+
print("šØ Testing with cyberpunk theme...")
|
|
121
|
+
ui = CoordinationUI(
|
|
122
|
+
display_type="rich_terminal",
|
|
123
|
+
theme="cyberpunk",
|
|
124
|
+
refresh_rate=4,
|
|
125
|
+
enable_syntax_highlighting=True,
|
|
126
|
+
max_content_lines=12,
|
|
127
|
+
logging_enabled=True,
|
|
128
|
+
)
|
|
129
|
+
|
|
130
|
+
print("š„ Created two-agent system with Rich display:")
|
|
131
|
+
print(" ⨠Creative - Storytelling and imagination")
|
|
132
|
+
print(" š§ Technical - Precision and technical depth")
|
|
133
|
+
print()
|
|
134
|
+
|
|
135
|
+
# Test question for rich display
|
|
136
|
+
test_question = "Explain how artificial intelligence works, making it both technically accurate and engaging for a general audience."
|
|
137
|
+
|
|
138
|
+
print(f"š Question: {test_question}")
|
|
139
|
+
print("\nš Starting Rich UI coordination...")
|
|
140
|
+
print("=" * 60)
|
|
141
|
+
|
|
142
|
+
# Coordinate with Rich UI
|
|
143
|
+
final_response = await ui.coordinate(orchestrator, test_question)
|
|
144
|
+
|
|
145
|
+
print("\n" + "=" * 60)
|
|
146
|
+
print("ā
Rich display coordination completed!")
|
|
147
|
+
print(f"š Final response length: {len(final_response)} characters")
|
|
148
|
+
|
|
149
|
+
return True
|
|
150
|
+
|
|
151
|
+
except Exception as e:
|
|
152
|
+
print(f"ā Rich display coordination test failed: {e}")
|
|
153
|
+
import traceback
|
|
154
|
+
|
|
155
|
+
traceback.print_exc()
|
|
156
|
+
return False
|
|
157
|
+
|
|
158
|
+
|
|
159
|
+
async def test_rich_convenience_function():
|
|
160
|
+
"""Test the coordinate_with_rich_ui convenience function."""
|
|
161
|
+
print("\nš Rich UI Convenience Function Test")
|
|
162
|
+
print("-" * 40)
|
|
163
|
+
|
|
164
|
+
if not is_rich_available():
|
|
165
|
+
print("ā ļø Skipping - Rich library not available")
|
|
166
|
+
return False
|
|
167
|
+
|
|
168
|
+
api_key = os.getenv("OPENAI_API_KEY")
|
|
169
|
+
if not api_key:
|
|
170
|
+
print("ā OPENAI_API_KEY not found - skipping convenience function test")
|
|
171
|
+
return False
|
|
172
|
+
|
|
173
|
+
try:
|
|
174
|
+
# Create backend and agents
|
|
175
|
+
backend = ResponseBackend(api_key=api_key)
|
|
176
|
+
|
|
177
|
+
analyst = SingleAgent(
|
|
178
|
+
backend=backend,
|
|
179
|
+
agent_id="analyst",
|
|
180
|
+
system_message="You are a data analyst who provides clear analytical insights and interpretations.",
|
|
181
|
+
)
|
|
182
|
+
|
|
183
|
+
strategist = SingleAgent(
|
|
184
|
+
backend=backend,
|
|
185
|
+
agent_id="strategist",
|
|
186
|
+
system_message="You are a strategic thinker who focuses on long-term implications and strategic recommendations.",
|
|
187
|
+
)
|
|
188
|
+
|
|
189
|
+
orchestrator = Orchestrator(
|
|
190
|
+
agents={"analyst": analyst, "strategist": strategist}
|
|
191
|
+
)
|
|
192
|
+
|
|
193
|
+
print("šÆ Testing convenience function with light theme...")
|
|
194
|
+
|
|
195
|
+
# Use convenience function with light theme
|
|
196
|
+
test_question = "What are the key trends in renewable energy adoption?"
|
|
197
|
+
|
|
198
|
+
print(f"š Question: {test_question}")
|
|
199
|
+
print("\nš Using coordinate_with_rich_ui()...")
|
|
200
|
+
print("=" * 60)
|
|
201
|
+
|
|
202
|
+
final_response = await coordinate_with_rich_ui(
|
|
203
|
+
orchestrator,
|
|
204
|
+
test_question,
|
|
205
|
+
theme="light",
|
|
206
|
+
refresh_rate=6,
|
|
207
|
+
enable_syntax_highlighting=True,
|
|
208
|
+
)
|
|
209
|
+
|
|
210
|
+
print("\n" + "=" * 60)
|
|
211
|
+
print("ā
Convenience function test completed!")
|
|
212
|
+
print(f"š Final response length: {len(final_response)} characters")
|
|
213
|
+
|
|
214
|
+
return True
|
|
215
|
+
|
|
216
|
+
except Exception as e:
|
|
217
|
+
print(f"ā Convenience function test failed: {e}")
|
|
218
|
+
import traceback
|
|
219
|
+
|
|
220
|
+
traceback.print_exc()
|
|
221
|
+
return False
|
|
222
|
+
|
|
223
|
+
|
|
224
|
+
async def test_rich_fallback():
|
|
225
|
+
"""Test fallback behavior when Rich is not available."""
|
|
226
|
+
print("\nš Rich Fallback Test")
|
|
227
|
+
print("-" * 40)
|
|
228
|
+
|
|
229
|
+
# This test simulates Rich not being available
|
|
230
|
+
# We can't actually uninstall Rich during runtime, so we test the UI logic
|
|
231
|
+
|
|
232
|
+
try:
|
|
233
|
+
# Test UI creation with rich_terminal when Rich is available
|
|
234
|
+
ui = CoordinationUI(display_type="rich_terminal")
|
|
235
|
+
|
|
236
|
+
if is_rich_available():
|
|
237
|
+
print("ā
Rich is available - RichTerminalDisplay should be used")
|
|
238
|
+
from massgen.frontend.displays.rich_terminal_display import (
|
|
239
|
+
RichTerminalDisplay,
|
|
240
|
+
)
|
|
241
|
+
|
|
242
|
+
# Note: We can't easily test the actual fallback without mocking
|
|
243
|
+
print("š Note: Fallback logic tested through UI creation")
|
|
244
|
+
else:
|
|
245
|
+
print("ā
Rich not available - fallback to TerminalDisplay should occur")
|
|
246
|
+
|
|
247
|
+
return True
|
|
248
|
+
|
|
249
|
+
except Exception as e:
|
|
250
|
+
print(f"ā Fallback test failed: {e}")
|
|
251
|
+
return False
|
|
252
|
+
|
|
253
|
+
|
|
254
|
+
async def test_rich_themes():
|
|
255
|
+
"""Test different Rich themes and configurations."""
|
|
256
|
+
print("\nšØ Rich Themes Test")
|
|
257
|
+
print("-" * 40)
|
|
258
|
+
|
|
259
|
+
if not is_rich_available():
|
|
260
|
+
print("ā ļø Skipping - Rich library not available")
|
|
261
|
+
return False
|
|
262
|
+
|
|
263
|
+
try:
|
|
264
|
+
from massgen.frontend.displays.rich_terminal_display import RichTerminalDisplay
|
|
265
|
+
|
|
266
|
+
agent_ids = ["agent1", "agent2"]
|
|
267
|
+
themes_to_test = [
|
|
268
|
+
("dark", "Default dark theme"),
|
|
269
|
+
("light", "Light theme for bright environments"),
|
|
270
|
+
("cyberpunk", "Cyberpunk theme with vibrant colors"),
|
|
271
|
+
]
|
|
272
|
+
|
|
273
|
+
for theme, description in themes_to_test:
|
|
274
|
+
print(f"šØ Testing {theme} theme: {description}")
|
|
275
|
+
|
|
276
|
+
display = RichTerminalDisplay(
|
|
277
|
+
agent_ids,
|
|
278
|
+
theme=theme,
|
|
279
|
+
refresh_rate=8,
|
|
280
|
+
enable_syntax_highlighting=True,
|
|
281
|
+
max_content_lines=20,
|
|
282
|
+
show_timestamps=True,
|
|
283
|
+
)
|
|
284
|
+
|
|
285
|
+
# Test theme-specific color configuration
|
|
286
|
+
colors = display.colors
|
|
287
|
+
print(f" - Primary color: {colors['primary']}")
|
|
288
|
+
print(f" - Success color: {colors['success']}")
|
|
289
|
+
print(f" - Border style: {colors['border']}")
|
|
290
|
+
|
|
291
|
+
display.cleanup()
|
|
292
|
+
print(f"ā
{theme.title()} theme test passed")
|
|
293
|
+
|
|
294
|
+
return True
|
|
295
|
+
|
|
296
|
+
except Exception as e:
|
|
297
|
+
print(f"ā Themes test failed: {e}")
|
|
298
|
+
import traceback
|
|
299
|
+
|
|
300
|
+
traceback.print_exc()
|
|
301
|
+
return False
|
|
302
|
+
|
|
303
|
+
|
|
304
|
+
async def main():
|
|
305
|
+
"""Run Rich Terminal Display test suite."""
|
|
306
|
+
print("šØ MassGen - Rich Terminal Display Test Suite")
|
|
307
|
+
print("=" * 60)
|
|
308
|
+
|
|
309
|
+
results = []
|
|
310
|
+
|
|
311
|
+
# Test Rich availability
|
|
312
|
+
results.append(await test_rich_availability())
|
|
313
|
+
|
|
314
|
+
# Only run Rich-specific tests if Rich is available
|
|
315
|
+
if results[0]:
|
|
316
|
+
# Test basic Rich display functionality
|
|
317
|
+
results.append(await test_rich_display_basic())
|
|
318
|
+
|
|
319
|
+
# Test themes
|
|
320
|
+
results.append(await test_rich_themes())
|
|
321
|
+
|
|
322
|
+
# Test with actual coordination if API key is available
|
|
323
|
+
if os.getenv("OPENAI_API_KEY"):
|
|
324
|
+
results.append(await test_rich_display_coordination())
|
|
325
|
+
results.append(await test_rich_convenience_function())
|
|
326
|
+
else:
|
|
327
|
+
print("\nā ļø Skipping coordination tests - OPENAI_API_KEY not found")
|
|
328
|
+
results.extend([True, True]) # Skip but don't fail
|
|
329
|
+
else:
|
|
330
|
+
print("\nā ļø Skipping Rich-specific tests - Rich library not available")
|
|
331
|
+
results.extend([False, False, False, False])
|
|
332
|
+
|
|
333
|
+
# Test fallback behavior
|
|
334
|
+
results.append(await test_rich_fallback())
|
|
335
|
+
|
|
336
|
+
# Summary
|
|
337
|
+
print("\n" + "=" * 60)
|
|
338
|
+
print("š Rich Terminal Display Test Results:")
|
|
339
|
+
|
|
340
|
+
test_names = [
|
|
341
|
+
"Rich Availability",
|
|
342
|
+
"Basic Display",
|
|
343
|
+
"Theme Configuration",
|
|
344
|
+
"Coordination Test",
|
|
345
|
+
"Convenience Function",
|
|
346
|
+
"Fallback Behavior",
|
|
347
|
+
]
|
|
348
|
+
|
|
349
|
+
for i, (test_name, result) in enumerate(zip(test_names, results)):
|
|
350
|
+
status = "ā
PASS" if result else "ā FAIL"
|
|
351
|
+
print(f" {status} {test_name}")
|
|
352
|
+
|
|
353
|
+
passed = sum(results)
|
|
354
|
+
total = len(results)
|
|
355
|
+
|
|
356
|
+
print(f"\nš Summary: {passed}/{total} tests passed")
|
|
357
|
+
|
|
358
|
+
if all(results):
|
|
359
|
+
print("š All Rich Terminal Display tests passed!")
|
|
360
|
+
if is_rich_available():
|
|
361
|
+
print("ā
Rich Terminal Display is working correctly")
|
|
362
|
+
else:
|
|
363
|
+
print("ā
Fallback behavior is working correctly")
|
|
364
|
+
else:
|
|
365
|
+
if not is_rich_available():
|
|
366
|
+
print("š” Install Rich library with: pip install rich")
|
|
367
|
+
print("ā ļø Some tests failed - check installation and configuration")
|
|
368
|
+
|
|
369
|
+
print("\nš Rich Terminal Display provides enhanced visualization with:")
|
|
370
|
+
print(" šØ Beautiful themes and colors")
|
|
371
|
+
print(" š Live updating layouts")
|
|
372
|
+
print(" š» Syntax highlighting")
|
|
373
|
+
print(" š Smooth refresh animations")
|
|
374
|
+
print(" š± Responsive design")
|
|
375
|
+
|
|
376
|
+
|
|
377
|
+
if __name__ == "__main__":
|
|
378
|
+
asyncio.run(main())
|