massgen 0.1.1__py3-none-any.whl → 0.1.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.
Files changed (77) hide show
  1. massgen/__init__.py +1 -1
  2. massgen/agent_config.py +33 -7
  3. massgen/api_params_handler/_api_params_handler_base.py +3 -0
  4. massgen/api_params_handler/_chat_completions_api_params_handler.py +7 -1
  5. massgen/backend/azure_openai.py +9 -1
  6. massgen/backend/base.py +56 -0
  7. massgen/backend/base_with_custom_tool_and_mcp.py +4 -4
  8. massgen/backend/capabilities.py +6 -6
  9. massgen/backend/chat_completions.py +18 -11
  10. massgen/backend/claude_code.py +9 -1
  11. massgen/backend/gemini.py +71 -6
  12. massgen/backend/gemini_utils.py +30 -0
  13. massgen/backend/grok.py +39 -6
  14. massgen/backend/response.py +18 -11
  15. massgen/chat_agent.py +9 -3
  16. massgen/cli.py +319 -43
  17. massgen/config_builder.py +163 -18
  18. massgen/configs/README.md +78 -20
  19. massgen/configs/basic/multi/three_agents_default.yaml +2 -2
  20. massgen/configs/debug/restart_test_controlled.yaml +60 -0
  21. massgen/configs/debug/restart_test_controlled_filesystem.yaml +73 -0
  22. massgen/configs/tools/code-execution/docker_with_sudo.yaml +35 -0
  23. massgen/configs/tools/custom_tools/computer_use_browser_example.yaml +56 -0
  24. massgen/configs/tools/custom_tools/computer_use_docker_example.yaml +65 -0
  25. massgen/configs/tools/custom_tools/computer_use_example.yaml +50 -0
  26. massgen/configs/tools/custom_tools/crawl4ai_mcp_example.yaml +67 -0
  27. massgen/configs/tools/custom_tools/crawl4ai_multi_agent_example.yaml +68 -0
  28. massgen/configs/tools/custom_tools/multimodal_tools/playwright_with_img_understanding.yaml +98 -0
  29. massgen/configs/tools/custom_tools/multimodal_tools/understand_audio.yaml +33 -0
  30. massgen/configs/tools/custom_tools/multimodal_tools/understand_file.yaml +34 -0
  31. massgen/configs/tools/custom_tools/multimodal_tools/understand_image.yaml +33 -0
  32. massgen/configs/tools/custom_tools/multimodal_tools/understand_video.yaml +34 -0
  33. massgen/configs/tools/custom_tools/multimodal_tools/understand_video_example.yaml +54 -0
  34. massgen/configs/tools/custom_tools/multimodal_tools/youtube_video_analysis.yaml +59 -0
  35. massgen/configs/tools/memory/README.md +199 -0
  36. massgen/configs/tools/memory/gpt5mini_gemini_context_window_management.yaml +131 -0
  37. massgen/configs/tools/memory/gpt5mini_gemini_no_persistent_memory.yaml +133 -0
  38. massgen/configs/tools/memory/test_context_window_management.py +286 -0
  39. massgen/configs/tools/multimodal/gpt5mini_gpt5nano_documentation_evolution.yaml +97 -0
  40. massgen/configs/tools/planning/five_agents_discord_mcp_planning_mode.yaml +7 -29
  41. massgen/configs/tools/planning/five_agents_filesystem_mcp_planning_mode.yaml +5 -6
  42. massgen/configs/tools/planning/five_agents_notion_mcp_planning_mode.yaml +4 -4
  43. massgen/configs/tools/planning/five_agents_twitter_mcp_planning_mode.yaml +4 -4
  44. massgen/configs/tools/planning/gpt5_mini_case_study_mcp_planning_mode.yaml +2 -2
  45. massgen/docker/README.md +83 -0
  46. massgen/filesystem_manager/_code_execution_server.py +22 -7
  47. massgen/filesystem_manager/_docker_manager.py +21 -1
  48. massgen/filesystem_manager/_filesystem_manager.py +8 -0
  49. massgen/filesystem_manager/_workspace_tools_server.py +0 -997
  50. massgen/formatter/_gemini_formatter.py +73 -0
  51. massgen/frontend/coordination_ui.py +175 -257
  52. massgen/frontend/displays/base_display.py +29 -0
  53. massgen/frontend/displays/rich_terminal_display.py +155 -9
  54. massgen/frontend/displays/simple_display.py +21 -0
  55. massgen/frontend/displays/terminal_display.py +22 -2
  56. massgen/logger_config.py +50 -6
  57. massgen/message_templates.py +123 -3
  58. massgen/orchestrator.py +652 -44
  59. massgen/tests/test_code_execution.py +178 -0
  60. massgen/tests/test_intelligent_planning_mode.py +643 -0
  61. massgen/tests/test_orchestration_restart.py +204 -0
  62. massgen/token_manager/token_manager.py +13 -4
  63. massgen/tool/__init__.py +4 -0
  64. massgen/tool/_multimodal_tools/understand_audio.py +193 -0
  65. massgen/tool/_multimodal_tools/understand_file.py +550 -0
  66. massgen/tool/_multimodal_tools/understand_image.py +212 -0
  67. massgen/tool/_multimodal_tools/understand_video.py +313 -0
  68. massgen/tool/docs/multimodal_tools.md +779 -0
  69. massgen/tool/workflow_toolkits/__init__.py +26 -0
  70. massgen/tool/workflow_toolkits/post_evaluation.py +216 -0
  71. massgen/utils.py +1 -0
  72. {massgen-0.1.1.dist-info → massgen-0.1.3.dist-info}/METADATA +57 -52
  73. {massgen-0.1.1.dist-info → massgen-0.1.3.dist-info}/RECORD +77 -49
  74. {massgen-0.1.1.dist-info → massgen-0.1.3.dist-info}/WHEEL +0 -0
  75. {massgen-0.1.1.dist-info → massgen-0.1.3.dist-info}/entry_points.txt +0 -0
  76. {massgen-0.1.1.dist-info → massgen-0.1.3.dist-info}/licenses/LICENSE +0 -0
  77. {massgen-0.1.1.dist-info → massgen-0.1.3.dist-info}/top_level.txt +0 -0
@@ -154,6 +154,112 @@ class TestCommandSanitization:
154
154
  _sanitize_command(cmd)
155
155
 
156
156
 
157
+ class TestSudoSanitization:
158
+ """Test sudo sanitization respects enable_sudo flag."""
159
+
160
+ def test_sudo_blocked_by_default(self):
161
+ """Test that sudo is blocked when enable_sudo=False (default)."""
162
+ from massgen.filesystem_manager._code_execution_server import _sanitize_command
163
+
164
+ sudo_commands = [
165
+ "sudo apt-get update",
166
+ "sudo apt-get install -y ffmpeg",
167
+ "sudo pip install tensorflow",
168
+ "sudo npm install -g typescript",
169
+ "sudo chmod 755 file.txt",
170
+ "echo 'test' && sudo apt update",
171
+ ]
172
+
173
+ for cmd in sudo_commands:
174
+ with pytest.raises(ValueError, match="sudo.*not allowed"):
175
+ _sanitize_command(cmd, enable_sudo=False)
176
+
177
+ def test_sudo_allowed_when_enabled(self):
178
+ """Test that sudo is allowed when enable_sudo=True."""
179
+ from massgen.filesystem_manager._code_execution_server import _sanitize_command
180
+
181
+ sudo_commands = [
182
+ "sudo apt-get update",
183
+ "sudo apt-get install -y ffmpeg",
184
+ "sudo pip install tensorflow",
185
+ "sudo npm install -g typescript",
186
+ "sudo chown user:group file.txt", # chown allowed with sudo enabled
187
+ "sudo chmod 755 file.txt", # chmod allowed with sudo enabled
188
+ ]
189
+
190
+ for cmd in sudo_commands:
191
+ # Should not raise when enable_sudo=True
192
+ _sanitize_command(cmd, enable_sudo=True)
193
+
194
+ def test_other_dangerous_patterns_still_blocked_with_sudo(self):
195
+ """Test that other dangerous patterns are still blocked even with sudo enabled."""
196
+ from massgen.filesystem_manager._code_execution_server import _sanitize_command
197
+
198
+ # These should ALWAYS be blocked, regardless of enable_sudo
199
+ dangerous_commands = [
200
+ "sudo rm -rf /", # Still blocked - root deletion
201
+ "rm -rf /", # Still blocked
202
+ "dd if=/dev/zero of=/dev/sda", # Still blocked - dd command
203
+ "sudo dd if=/dev/zero of=/dev/sda", # Still blocked
204
+ ":(){ :|:& };:", # Still blocked - fork bomb
205
+ "mv file /dev/null", # Still blocked
206
+ "sudo mv file /dev/null", # Still blocked
207
+ "echo test > /dev/sda1", # Still blocked - writing to disk
208
+ ]
209
+
210
+ for cmd in dangerous_commands:
211
+ with pytest.raises(ValueError, match="dangerous|not allowed"):
212
+ _sanitize_command(cmd, enable_sudo=True)
213
+
214
+ def test_su_chown_chmod_blocked_without_sudo_flag(self):
215
+ """Test that su, chown, chmod are blocked when enable_sudo=False."""
216
+ from massgen.filesystem_manager._code_execution_server import _sanitize_command
217
+
218
+ commands = [
219
+ "su root",
220
+ "su - postgres",
221
+ "chown root:root file.txt",
222
+ "chmod 777 file.txt",
223
+ "chmod +x script.sh",
224
+ ]
225
+
226
+ for cmd in commands:
227
+ with pytest.raises(ValueError, match="not allowed"):
228
+ _sanitize_command(cmd, enable_sudo=False)
229
+
230
+ def test_su_chown_chmod_allowed_with_sudo_flag(self):
231
+ """Test that su, chown, chmod are allowed when enable_sudo=True (Docker sudo mode)."""
232
+ from massgen.filesystem_manager._code_execution_server import _sanitize_command
233
+
234
+ # In Docker sudo mode, these are safe because they're confined to container
235
+ commands = [
236
+ "su postgres",
237
+ "chown user:group file.txt",
238
+ "chmod 755 file.txt",
239
+ "chmod +x script.sh",
240
+ ]
241
+
242
+ for cmd in commands:
243
+ # Should not raise when enable_sudo=True
244
+ _sanitize_command(cmd, enable_sudo=True)
245
+
246
+ def test_local_mode_blocks_sudo(self):
247
+ """Test that local mode (non-Docker) blocks sudo commands."""
248
+ from massgen.filesystem_manager._code_execution_server import _sanitize_command
249
+
250
+ # In local mode (enable_sudo=False), sudo should be blocked for safety
251
+ with pytest.raises(ValueError, match="sudo.*not allowed"):
252
+ _sanitize_command("sudo apt-get install malicious-package", enable_sudo=False)
253
+
254
+ def test_docker_sudo_mode_allows_sudo(self):
255
+ """Test that Docker sudo mode allows sudo commands."""
256
+ from massgen.filesystem_manager._code_execution_server import _sanitize_command
257
+
258
+ # In Docker mode with enable_sudo=True, sudo should be allowed
259
+ # (safe because it's inside container)
260
+ _sanitize_command("sudo apt-get install gh", enable_sudo=True)
261
+
262
+
157
263
  class TestOutputHandling:
158
264
  """Test output capture and size limits."""
159
265
 
@@ -674,6 +780,78 @@ class TestDockerExecution:
674
780
  # Cleanup
675
781
  manager.cleanup("test_context")
676
782
 
783
+ @pytest.mark.docker
784
+ def test_docker_sudo_enabled_image_selection(self):
785
+ """Test that enabling sudo automatically selects the sudo image variant."""
786
+ from massgen.filesystem_manager._docker_manager import DockerManager
787
+
788
+ # Test 1: Default image with sudo=False should use regular image
789
+ manager_no_sudo = DockerManager(enable_sudo=False)
790
+ assert manager_no_sudo.image == "massgen/mcp-runtime:latest"
791
+ assert manager_no_sudo.enable_sudo is False
792
+
793
+ # Test 2: Default image with sudo=True should auto-switch to sudo variant
794
+ manager_with_sudo = DockerManager(enable_sudo=True)
795
+ assert manager_with_sudo.image == "massgen/mcp-runtime-sudo:latest"
796
+ assert manager_with_sudo.enable_sudo is True
797
+
798
+ # Test 3: Custom image with sudo=True should keep custom image
799
+ manager_custom = DockerManager(
800
+ image="my-custom-image:latest",
801
+ enable_sudo=True,
802
+ )
803
+ assert manager_custom.image == "my-custom-image:latest"
804
+ assert manager_custom.enable_sudo is True
805
+
806
+ @pytest.mark.docker
807
+ def test_docker_sudo_functionality(self, tmp_path):
808
+ """Test that sudo commands work in sudo-enabled container."""
809
+ from massgen.filesystem_manager._docker_manager import DockerManager
810
+
811
+ # Skip if sudo image not built
812
+ manager = DockerManager(enable_sudo=True)
813
+ try:
814
+ manager.ensure_image_exists()
815
+ except RuntimeError:
816
+ pytest.skip("Sudo Docker image not built. Run: bash massgen/docker/build.sh --sudo")
817
+
818
+ workspace = tmp_path / "workspace_sudo"
819
+ workspace.mkdir()
820
+
821
+ # Create container with sudo enabled
822
+ manager.create_container(
823
+ agent_id="test_sudo",
824
+ workspace_path=workspace,
825
+ )
826
+
827
+ # Test 1: Verify whoami returns 'massgen' (non-root user)
828
+ result_whoami = manager.exec_command(
829
+ agent_id="test_sudo",
830
+ command="whoami",
831
+ )
832
+ assert result_whoami["success"] is True
833
+ assert "massgen" in result_whoami["stdout"]
834
+
835
+ # Test 2: Verify sudo whoami returns 'root' (sudo works)
836
+ result_sudo_whoami = manager.exec_command(
837
+ agent_id="test_sudo",
838
+ command="sudo whoami",
839
+ )
840
+ assert result_sudo_whoami["success"] is True
841
+ assert "root" in result_sudo_whoami["stdout"]
842
+
843
+ # Test 3: Verify sudo apt-get update works (package installation capability)
844
+ result_apt = manager.exec_command(
845
+ agent_id="test_sudo",
846
+ command="sudo apt-get update",
847
+ timeout=60,
848
+ )
849
+ # This should succeed in sudo image (may fail in network=none, but command should run)
850
+ assert result_apt["exit_code"] is not None
851
+
852
+ # Cleanup
853
+ manager.cleanup("test_sudo")
854
+
677
855
 
678
856
  if __name__ == "__main__":
679
857
  pytest.main([__file__, "-v"])