amd-gaia 0.15.0__py3-none-any.whl → 0.15.1__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.
- {amd_gaia-0.15.0.dist-info → amd_gaia-0.15.1.dist-info}/METADATA +223 -223
- amd_gaia-0.15.1.dist-info/RECORD +178 -0
- {amd_gaia-0.15.0.dist-info → amd_gaia-0.15.1.dist-info}/entry_points.txt +1 -0
- {amd_gaia-0.15.0.dist-info → amd_gaia-0.15.1.dist-info}/licenses/LICENSE.md +20 -20
- gaia/__init__.py +29 -29
- gaia/agents/__init__.py +19 -19
- gaia/agents/base/__init__.py +9 -9
- gaia/agents/base/agent.py +2177 -2177
- gaia/agents/base/api_agent.py +120 -120
- gaia/agents/base/console.py +1841 -1841
- gaia/agents/base/errors.py +237 -237
- gaia/agents/base/mcp_agent.py +86 -86
- gaia/agents/base/tools.py +83 -83
- gaia/agents/blender/agent.py +556 -556
- gaia/agents/blender/agent_simple.py +133 -135
- gaia/agents/blender/app.py +211 -211
- gaia/agents/blender/app_simple.py +41 -41
- gaia/agents/blender/core/__init__.py +16 -16
- gaia/agents/blender/core/materials.py +506 -506
- gaia/agents/blender/core/objects.py +316 -316
- gaia/agents/blender/core/rendering.py +225 -225
- gaia/agents/blender/core/scene.py +220 -220
- gaia/agents/blender/core/view.py +146 -146
- gaia/agents/chat/__init__.py +9 -9
- gaia/agents/chat/agent.py +835 -835
- gaia/agents/chat/app.py +1058 -1058
- gaia/agents/chat/session.py +508 -508
- gaia/agents/chat/tools/__init__.py +15 -15
- gaia/agents/chat/tools/file_tools.py +96 -96
- gaia/agents/chat/tools/rag_tools.py +1729 -1729
- gaia/agents/chat/tools/shell_tools.py +436 -436
- gaia/agents/code/__init__.py +7 -7
- gaia/agents/code/agent.py +549 -549
- gaia/agents/code/cli.py +377 -0
- gaia/agents/code/models.py +135 -135
- gaia/agents/code/orchestration/__init__.py +24 -24
- gaia/agents/code/orchestration/checklist_executor.py +1763 -1763
- gaia/agents/code/orchestration/checklist_generator.py +713 -713
- gaia/agents/code/orchestration/factories/__init__.py +9 -9
- gaia/agents/code/orchestration/factories/base.py +63 -63
- gaia/agents/code/orchestration/factories/nextjs_factory.py +118 -118
- gaia/agents/code/orchestration/factories/python_factory.py +106 -106
- gaia/agents/code/orchestration/orchestrator.py +841 -841
- gaia/agents/code/orchestration/project_analyzer.py +391 -391
- gaia/agents/code/orchestration/steps/__init__.py +67 -67
- gaia/agents/code/orchestration/steps/base.py +188 -188
- gaia/agents/code/orchestration/steps/error_handler.py +314 -314
- gaia/agents/code/orchestration/steps/nextjs.py +828 -828
- gaia/agents/code/orchestration/steps/python.py +307 -307
- gaia/agents/code/orchestration/template_catalog.py +469 -469
- gaia/agents/code/orchestration/workflows/__init__.py +14 -14
- gaia/agents/code/orchestration/workflows/base.py +80 -80
- gaia/agents/code/orchestration/workflows/nextjs.py +186 -186
- gaia/agents/code/orchestration/workflows/python.py +94 -94
- gaia/agents/code/prompts/__init__.py +11 -11
- gaia/agents/code/prompts/base_prompt.py +77 -77
- gaia/agents/code/prompts/code_patterns.py +2036 -2036
- gaia/agents/code/prompts/nextjs_prompt.py +40 -40
- gaia/agents/code/prompts/python_prompt.py +109 -109
- gaia/agents/code/schema_inference.py +365 -365
- gaia/agents/code/system_prompt.py +41 -41
- gaia/agents/code/tools/__init__.py +42 -42
- gaia/agents/code/tools/cli_tools.py +1138 -1138
- gaia/agents/code/tools/code_formatting.py +319 -319
- gaia/agents/code/tools/code_tools.py +769 -769
- gaia/agents/code/tools/error_fixing.py +1347 -1347
- gaia/agents/code/tools/external_tools.py +180 -180
- gaia/agents/code/tools/file_io.py +845 -845
- gaia/agents/code/tools/prisma_tools.py +190 -190
- gaia/agents/code/tools/project_management.py +1016 -1016
- gaia/agents/code/tools/testing.py +321 -321
- gaia/agents/code/tools/typescript_tools.py +122 -122
- gaia/agents/code/tools/validation_parsing.py +461 -461
- gaia/agents/code/tools/validation_tools.py +806 -806
- gaia/agents/code/tools/web_dev_tools.py +1758 -1758
- gaia/agents/code/validators/__init__.py +16 -16
- gaia/agents/code/validators/antipattern_checker.py +241 -241
- gaia/agents/code/validators/ast_analyzer.py +197 -197
- gaia/agents/code/validators/requirements_validator.py +145 -145
- gaia/agents/code/validators/syntax_validator.py +171 -171
- gaia/agents/docker/__init__.py +7 -7
- gaia/agents/docker/agent.py +642 -642
- gaia/agents/emr/__init__.py +8 -8
- gaia/agents/emr/agent.py +1506 -1506
- gaia/agents/emr/cli.py +1322 -1322
- gaia/agents/emr/constants.py +475 -475
- gaia/agents/emr/dashboard/__init__.py +4 -4
- gaia/agents/emr/dashboard/server.py +1974 -1974
- gaia/agents/jira/__init__.py +11 -11
- gaia/agents/jira/agent.py +894 -894
- gaia/agents/jira/jql_templates.py +299 -299
- gaia/agents/routing/__init__.py +7 -7
- gaia/agents/routing/agent.py +567 -570
- gaia/agents/routing/system_prompt.py +75 -75
- gaia/agents/summarize/__init__.py +11 -0
- gaia/agents/summarize/agent.py +885 -0
- gaia/agents/summarize/prompts.py +129 -0
- gaia/api/__init__.py +23 -23
- gaia/api/agent_registry.py +238 -238
- gaia/api/app.py +305 -305
- gaia/api/openai_server.py +575 -575
- gaia/api/schemas.py +186 -186
- gaia/api/sse_handler.py +373 -373
- gaia/apps/__init__.py +4 -4
- gaia/apps/llm/__init__.py +6 -6
- gaia/apps/llm/app.py +173 -169
- gaia/apps/summarize/app.py +116 -633
- gaia/apps/summarize/html_viewer.py +133 -133
- gaia/apps/summarize/pdf_formatter.py +284 -284
- gaia/audio/__init__.py +2 -2
- gaia/audio/audio_client.py +439 -439
- gaia/audio/audio_recorder.py +269 -269
- gaia/audio/kokoro_tts.py +599 -599
- gaia/audio/whisper_asr.py +432 -432
- gaia/chat/__init__.py +16 -16
- gaia/chat/app.py +430 -430
- gaia/chat/prompts.py +522 -522
- gaia/chat/sdk.py +1228 -1225
- gaia/cli.py +5481 -5632
- gaia/database/__init__.py +10 -10
- gaia/database/agent.py +176 -176
- gaia/database/mixin.py +290 -290
- gaia/database/testing.py +64 -64
- gaia/eval/batch_experiment.py +2332 -2332
- gaia/eval/claude.py +542 -542
- gaia/eval/config.py +37 -37
- gaia/eval/email_generator.py +512 -512
- gaia/eval/eval.py +3179 -3179
- gaia/eval/groundtruth.py +1130 -1130
- gaia/eval/transcript_generator.py +582 -582
- gaia/eval/webapp/README.md +167 -167
- gaia/eval/webapp/package-lock.json +875 -875
- gaia/eval/webapp/package.json +20 -20
- gaia/eval/webapp/public/app.js +3402 -3402
- gaia/eval/webapp/public/index.html +87 -87
- gaia/eval/webapp/public/styles.css +3661 -3661
- gaia/eval/webapp/server.js +415 -415
- gaia/eval/webapp/test-setup.js +72 -72
- gaia/llm/__init__.py +9 -2
- gaia/llm/base_client.py +60 -0
- gaia/llm/exceptions.py +12 -0
- gaia/llm/factory.py +70 -0
- gaia/llm/lemonade_client.py +3236 -3221
- gaia/llm/lemonade_manager.py +294 -294
- gaia/llm/providers/__init__.py +9 -0
- gaia/llm/providers/claude.py +108 -0
- gaia/llm/providers/lemonade.py +120 -0
- gaia/llm/providers/openai_provider.py +79 -0
- gaia/llm/vlm_client.py +382 -382
- gaia/logger.py +189 -189
- gaia/mcp/agent_mcp_server.py +245 -245
- gaia/mcp/blender_mcp_client.py +138 -138
- gaia/mcp/blender_mcp_server.py +648 -648
- gaia/mcp/context7_cache.py +332 -332
- gaia/mcp/external_services.py +518 -518
- gaia/mcp/mcp_bridge.py +811 -550
- gaia/mcp/servers/__init__.py +6 -6
- gaia/mcp/servers/docker_mcp.py +83 -83
- gaia/perf_analysis.py +361 -0
- gaia/rag/__init__.py +10 -10
- gaia/rag/app.py +293 -293
- gaia/rag/demo.py +304 -304
- gaia/rag/pdf_utils.py +235 -235
- gaia/rag/sdk.py +2194 -2194
- gaia/security.py +163 -163
- gaia/talk/app.py +289 -289
- gaia/talk/sdk.py +538 -538
- gaia/testing/__init__.py +87 -87
- gaia/testing/assertions.py +330 -330
- gaia/testing/fixtures.py +333 -333
- gaia/testing/mocks.py +493 -493
- gaia/util.py +46 -46
- gaia/utils/__init__.py +33 -33
- gaia/utils/file_watcher.py +675 -675
- gaia/utils/parsing.py +223 -223
- gaia/version.py +100 -100
- amd_gaia-0.15.0.dist-info/RECORD +0 -168
- gaia/agents/code/app.py +0 -266
- gaia/llm/llm_client.py +0 -723
- {amd_gaia-0.15.0.dist-info → amd_gaia-0.15.1.dist-info}/WHEEL +0 -0
- {amd_gaia-0.15.0.dist-info → amd_gaia-0.15.1.dist-info}/top_level.txt +0 -0
|
@@ -1,220 +1,220 @@
|
|
|
1
|
-
# Copyright(C) 2025-2026 Advanced Micro Devices, Inc. All rights reserved.
|
|
2
|
-
# SPDX-License-Identifier: MIT
|
|
3
|
-
|
|
4
|
-
from typing import Dict
|
|
5
|
-
|
|
6
|
-
from gaia.mcp.blender_mcp_client import MCPClient
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
class SceneManager:
|
|
10
|
-
"""Manages Blender scene operations."""
|
|
11
|
-
|
|
12
|
-
def __init__(self, mcp: MCPClient):
|
|
13
|
-
self.mcp = mcp
|
|
14
|
-
|
|
15
|
-
def reset_scene(self) -> Dict:
|
|
16
|
-
"""Reset Blender to a clean state, removing all objects and unused data."""
|
|
17
|
-
|
|
18
|
-
def generate_reset_code():
|
|
19
|
-
return """
|
|
20
|
-
import bpy
|
|
21
|
-
|
|
22
|
-
# Select all objects
|
|
23
|
-
bpy.ops.object.select_all(action='SELECT')
|
|
24
|
-
|
|
25
|
-
# Delete all selected objects
|
|
26
|
-
bpy.ops.object.delete()
|
|
27
|
-
|
|
28
|
-
# Clear orphaned data
|
|
29
|
-
for block in bpy.data.meshes:
|
|
30
|
-
if block.users == 0:
|
|
31
|
-
bpy.data.meshes.remove(block)
|
|
32
|
-
|
|
33
|
-
for block in bpy.data.materials:
|
|
34
|
-
if block.users == 0:
|
|
35
|
-
bpy.data.materials.remove(block)
|
|
36
|
-
|
|
37
|
-
for block in bpy.data.textures:
|
|
38
|
-
if block.users == 0:
|
|
39
|
-
bpy.data.textures.remove(block)
|
|
40
|
-
|
|
41
|
-
for block in bpy.data.images:
|
|
42
|
-
if block.users == 0:
|
|
43
|
-
bpy.data.images.remove(block)
|
|
44
|
-
|
|
45
|
-
# Add default cube back (similar to Blender's default startup)
|
|
46
|
-
bpy.ops.mesh.primitive_cube_add(size=2, enter_editmode=False, align='WORLD', location=(0, 0, 0))
|
|
47
|
-
|
|
48
|
-
# Reset the default view
|
|
49
|
-
for area in bpy.context.screen.areas:
|
|
50
|
-
if area.type == 'VIEW_3D':
|
|
51
|
-
for region in area.regions:
|
|
52
|
-
if region.type == 'WINDOW':
|
|
53
|
-
# Updated context override syntax for Blender 4.4
|
|
54
|
-
with bpy.context.temp_override(area=area, region=region):
|
|
55
|
-
bpy.ops.view3d.view_all()
|
|
56
|
-
|
|
57
|
-
# Return info for the test verification
|
|
58
|
-
has_default_cube = False
|
|
59
|
-
for obj in bpy.context.scene.objects:
|
|
60
|
-
if obj.name.startswith("Cube") and obj.type == 'MESH':
|
|
61
|
-
has_default_cube = True
|
|
62
|
-
break
|
|
63
|
-
|
|
64
|
-
object_count = len(bpy.context.scene.objects)
|
|
65
|
-
|
|
66
|
-
# Set result variable that will be returned by the MCP addon
|
|
67
|
-
result = {
|
|
68
|
-
"has_default_cube": has_default_cube,
|
|
69
|
-
"object_count": object_count
|
|
70
|
-
}
|
|
71
|
-
|
|
72
|
-
print("Blender scene has been reset with default cube")
|
|
73
|
-
"""
|
|
74
|
-
|
|
75
|
-
response = self.mcp.execute_code(generate_reset_code())
|
|
76
|
-
# Extract the returned result from the MCP if available
|
|
77
|
-
if response.get("result") and isinstance(response["result"], dict):
|
|
78
|
-
return {"status": "success", **response["result"]}
|
|
79
|
-
# Add stdout to the response for debugging
|
|
80
|
-
if "stdout" in response:
|
|
81
|
-
return {"status": "success", "message": response.get("stdout", "")}
|
|
82
|
-
# Fallback
|
|
83
|
-
return {"status": "success"}
|
|
84
|
-
|
|
85
|
-
def clear_scene(self) -> Dict:
|
|
86
|
-
"""Remove all objects from the current Blender scene."""
|
|
87
|
-
|
|
88
|
-
def generate_clear_code():
|
|
89
|
-
return """
|
|
90
|
-
import bpy
|
|
91
|
-
|
|
92
|
-
# Select all objects
|
|
93
|
-
bpy.ops.object.select_all(action='SELECT')
|
|
94
|
-
# Delete all selected objects
|
|
95
|
-
bpy.ops.object.delete()
|
|
96
|
-
|
|
97
|
-
# Return info about the cleared scene
|
|
98
|
-
object_count = len(bpy.context.scene.objects)
|
|
99
|
-
result = {
|
|
100
|
-
"object_count": object_count,
|
|
101
|
-
"message": "Scene cleared successfully"
|
|
102
|
-
}
|
|
103
|
-
|
|
104
|
-
print("Scene cleared successfully")
|
|
105
|
-
"""
|
|
106
|
-
|
|
107
|
-
response = self.mcp.execute_code(generate_clear_code())
|
|
108
|
-
# Extract the returned result from the MCP if available
|
|
109
|
-
if response.get("result") and isinstance(response["result"], dict):
|
|
110
|
-
return {"status": "success", **response["result"]}
|
|
111
|
-
# Add stdout to the response for debugging
|
|
112
|
-
if "stdout" in response:
|
|
113
|
-
return {"status": "success", "message": response.get("stdout", "")}
|
|
114
|
-
# Fallback
|
|
115
|
-
return {"status": "success"}
|
|
116
|
-
|
|
117
|
-
def set_world_background_black(self) -> Dict:
|
|
118
|
-
"""Set the world background to black."""
|
|
119
|
-
|
|
120
|
-
def generate_code():
|
|
121
|
-
return """
|
|
122
|
-
import bpy
|
|
123
|
-
|
|
124
|
-
world = bpy.data.worlds["World"]
|
|
125
|
-
world.use_nodes = True
|
|
126
|
-
bg_node = world.node_tree.nodes["Background"]
|
|
127
|
-
bg_node.inputs[0].default_value = (0, 0, 0, 1) # Black
|
|
128
|
-
bg_node.inputs[1].default_value = 0 # Strength to 0
|
|
129
|
-
|
|
130
|
-
# Verify the world background is black
|
|
131
|
-
bg_color = world.node_tree.nodes["Background"].inputs[0].default_value[:3]
|
|
132
|
-
is_black = all(c < 0.01 for c in bg_color)
|
|
133
|
-
|
|
134
|
-
# Set result variable that will be returned by the MCP addon
|
|
135
|
-
result = {
|
|
136
|
-
"is_black": is_black,
|
|
137
|
-
"color": list(bg_color) if world else None
|
|
138
|
-
}
|
|
139
|
-
|
|
140
|
-
print("World background set to black")
|
|
141
|
-
"""
|
|
142
|
-
|
|
143
|
-
response = self.mcp.execute_code(generate_code())
|
|
144
|
-
# Extract the returned result from the MCP if available
|
|
145
|
-
if response.get("result") and isinstance(response["result"], dict):
|
|
146
|
-
return {"status": "success", **response["result"]}
|
|
147
|
-
# Add stdout to the response for debugging
|
|
148
|
-
if "stdout" in response:
|
|
149
|
-
return {"status": "success", "message": response.get("stdout", "")}
|
|
150
|
-
# Fallback
|
|
151
|
-
return {"status": "success"}
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
def generate_scene_diagnosis_code() -> str:
|
|
155
|
-
"""
|
|
156
|
-
Generates Python code that provides comprehensive diagnostics about the current Blender scene.
|
|
157
|
-
This includes information about all objects, materials, and potential issues.
|
|
158
|
-
|
|
159
|
-
Returns:
|
|
160
|
-
String containing Python code that can be executed in Blender
|
|
161
|
-
"""
|
|
162
|
-
code = """
|
|
163
|
-
import bpy
|
|
164
|
-
|
|
165
|
-
result = {"status": "processing", "objects": []}
|
|
166
|
-
|
|
167
|
-
# Get all objects in the scene
|
|
168
|
-
for obj in bpy.data.objects:
|
|
169
|
-
obj_info = {
|
|
170
|
-
"name": obj.name,
|
|
171
|
-
"type": obj.type,
|
|
172
|
-
"visible": obj.visible_get(),
|
|
173
|
-
"location": list(obj.location),
|
|
174
|
-
"scale": list(obj.scale),
|
|
175
|
-
"material_slots": len(obj.material_slots),
|
|
176
|
-
"has_materials": len(obj.material_slots) > 0 and obj.active_material is not None
|
|
177
|
-
}
|
|
178
|
-
|
|
179
|
-
# Add material info if available
|
|
180
|
-
if obj.active_material:
|
|
181
|
-
obj_info["active_material"] = {
|
|
182
|
-
"name": obj.active_material.name,
|
|
183
|
-
"has_diffuse_color": hasattr(obj.active_material, "diffuse_color"),
|
|
184
|
-
}
|
|
185
|
-
if hasattr(obj.active_material, "diffuse_color"):
|
|
186
|
-
obj_info["active_material"]["diffuse_color"] = list(obj.active_material.diffuse_color)
|
|
187
|
-
|
|
188
|
-
result["objects"].append(obj_info)
|
|
189
|
-
|
|
190
|
-
# Add overall scene info
|
|
191
|
-
result["object_count"] = len(result["objects"])
|
|
192
|
-
result["material_count"] = len(bpy.data.materials)
|
|
193
|
-
|
|
194
|
-
# Check for common issues
|
|
195
|
-
result["issues"] = []
|
|
196
|
-
|
|
197
|
-
# Check for objects without materials that typically need them
|
|
198
|
-
for obj in result["objects"]:
|
|
199
|
-
if obj["type"] in ["MESH", "CURVE", "SURFACE", "META", "FONT"] and not obj.get("has_materials", False):
|
|
200
|
-
result["issues"].append({
|
|
201
|
-
"type": "missing_material",
|
|
202
|
-
"object": obj["name"],
|
|
203
|
-
"message": f"Object '{obj['name']}' has no material assigned"
|
|
204
|
-
})
|
|
205
|
-
|
|
206
|
-
# Check for objects with unusual scales (potentially errors)
|
|
207
|
-
for obj in result["objects"]:
|
|
208
|
-
scales = obj.get("scale", [1, 1, 1])
|
|
209
|
-
if any(s < 0.0001 or s > 1000 for s in scales):
|
|
210
|
-
result["issues"].append({
|
|
211
|
-
"type": "unusual_scale",
|
|
212
|
-
"object": obj["name"],
|
|
213
|
-
"scale": scales,
|
|
214
|
-
"message": f"Object '{obj['name']}' has unusual scale: {scales}"
|
|
215
|
-
})
|
|
216
|
-
|
|
217
|
-
result["status"] = "success"
|
|
218
|
-
result
|
|
219
|
-
"""
|
|
220
|
-
return code
|
|
1
|
+
# Copyright(C) 2025-2026 Advanced Micro Devices, Inc. All rights reserved.
|
|
2
|
+
# SPDX-License-Identifier: MIT
|
|
3
|
+
|
|
4
|
+
from typing import Dict
|
|
5
|
+
|
|
6
|
+
from gaia.mcp.blender_mcp_client import MCPClient
|
|
7
|
+
|
|
8
|
+
|
|
9
|
+
class SceneManager:
|
|
10
|
+
"""Manages Blender scene operations."""
|
|
11
|
+
|
|
12
|
+
def __init__(self, mcp: MCPClient):
|
|
13
|
+
self.mcp = mcp
|
|
14
|
+
|
|
15
|
+
def reset_scene(self) -> Dict:
|
|
16
|
+
"""Reset Blender to a clean state, removing all objects and unused data."""
|
|
17
|
+
|
|
18
|
+
def generate_reset_code():
|
|
19
|
+
return """
|
|
20
|
+
import bpy
|
|
21
|
+
|
|
22
|
+
# Select all objects
|
|
23
|
+
bpy.ops.object.select_all(action='SELECT')
|
|
24
|
+
|
|
25
|
+
# Delete all selected objects
|
|
26
|
+
bpy.ops.object.delete()
|
|
27
|
+
|
|
28
|
+
# Clear orphaned data
|
|
29
|
+
for block in bpy.data.meshes:
|
|
30
|
+
if block.users == 0:
|
|
31
|
+
bpy.data.meshes.remove(block)
|
|
32
|
+
|
|
33
|
+
for block in bpy.data.materials:
|
|
34
|
+
if block.users == 0:
|
|
35
|
+
bpy.data.materials.remove(block)
|
|
36
|
+
|
|
37
|
+
for block in bpy.data.textures:
|
|
38
|
+
if block.users == 0:
|
|
39
|
+
bpy.data.textures.remove(block)
|
|
40
|
+
|
|
41
|
+
for block in bpy.data.images:
|
|
42
|
+
if block.users == 0:
|
|
43
|
+
bpy.data.images.remove(block)
|
|
44
|
+
|
|
45
|
+
# Add default cube back (similar to Blender's default startup)
|
|
46
|
+
bpy.ops.mesh.primitive_cube_add(size=2, enter_editmode=False, align='WORLD', location=(0, 0, 0))
|
|
47
|
+
|
|
48
|
+
# Reset the default view
|
|
49
|
+
for area in bpy.context.screen.areas:
|
|
50
|
+
if area.type == 'VIEW_3D':
|
|
51
|
+
for region in area.regions:
|
|
52
|
+
if region.type == 'WINDOW':
|
|
53
|
+
# Updated context override syntax for Blender 4.4
|
|
54
|
+
with bpy.context.temp_override(area=area, region=region):
|
|
55
|
+
bpy.ops.view3d.view_all()
|
|
56
|
+
|
|
57
|
+
# Return info for the test verification
|
|
58
|
+
has_default_cube = False
|
|
59
|
+
for obj in bpy.context.scene.objects:
|
|
60
|
+
if obj.name.startswith("Cube") and obj.type == 'MESH':
|
|
61
|
+
has_default_cube = True
|
|
62
|
+
break
|
|
63
|
+
|
|
64
|
+
object_count = len(bpy.context.scene.objects)
|
|
65
|
+
|
|
66
|
+
# Set result variable that will be returned by the MCP addon
|
|
67
|
+
result = {
|
|
68
|
+
"has_default_cube": has_default_cube,
|
|
69
|
+
"object_count": object_count
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
print("Blender scene has been reset with default cube")
|
|
73
|
+
"""
|
|
74
|
+
|
|
75
|
+
response = self.mcp.execute_code(generate_reset_code())
|
|
76
|
+
# Extract the returned result from the MCP if available
|
|
77
|
+
if response.get("result") and isinstance(response["result"], dict):
|
|
78
|
+
return {"status": "success", **response["result"]}
|
|
79
|
+
# Add stdout to the response for debugging
|
|
80
|
+
if "stdout" in response:
|
|
81
|
+
return {"status": "success", "message": response.get("stdout", "")}
|
|
82
|
+
# Fallback
|
|
83
|
+
return {"status": "success"}
|
|
84
|
+
|
|
85
|
+
def clear_scene(self) -> Dict:
|
|
86
|
+
"""Remove all objects from the current Blender scene."""
|
|
87
|
+
|
|
88
|
+
def generate_clear_code():
|
|
89
|
+
return """
|
|
90
|
+
import bpy
|
|
91
|
+
|
|
92
|
+
# Select all objects
|
|
93
|
+
bpy.ops.object.select_all(action='SELECT')
|
|
94
|
+
# Delete all selected objects
|
|
95
|
+
bpy.ops.object.delete()
|
|
96
|
+
|
|
97
|
+
# Return info about the cleared scene
|
|
98
|
+
object_count = len(bpy.context.scene.objects)
|
|
99
|
+
result = {
|
|
100
|
+
"object_count": object_count,
|
|
101
|
+
"message": "Scene cleared successfully"
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
print("Scene cleared successfully")
|
|
105
|
+
"""
|
|
106
|
+
|
|
107
|
+
response = self.mcp.execute_code(generate_clear_code())
|
|
108
|
+
# Extract the returned result from the MCP if available
|
|
109
|
+
if response.get("result") and isinstance(response["result"], dict):
|
|
110
|
+
return {"status": "success", **response["result"]}
|
|
111
|
+
# Add stdout to the response for debugging
|
|
112
|
+
if "stdout" in response:
|
|
113
|
+
return {"status": "success", "message": response.get("stdout", "")}
|
|
114
|
+
# Fallback
|
|
115
|
+
return {"status": "success"}
|
|
116
|
+
|
|
117
|
+
def set_world_background_black(self) -> Dict:
|
|
118
|
+
"""Set the world background to black."""
|
|
119
|
+
|
|
120
|
+
def generate_code():
|
|
121
|
+
return """
|
|
122
|
+
import bpy
|
|
123
|
+
|
|
124
|
+
world = bpy.data.worlds["World"]
|
|
125
|
+
world.use_nodes = True
|
|
126
|
+
bg_node = world.node_tree.nodes["Background"]
|
|
127
|
+
bg_node.inputs[0].default_value = (0, 0, 0, 1) # Black
|
|
128
|
+
bg_node.inputs[1].default_value = 0 # Strength to 0
|
|
129
|
+
|
|
130
|
+
# Verify the world background is black
|
|
131
|
+
bg_color = world.node_tree.nodes["Background"].inputs[0].default_value[:3]
|
|
132
|
+
is_black = all(c < 0.01 for c in bg_color)
|
|
133
|
+
|
|
134
|
+
# Set result variable that will be returned by the MCP addon
|
|
135
|
+
result = {
|
|
136
|
+
"is_black": is_black,
|
|
137
|
+
"color": list(bg_color) if world else None
|
|
138
|
+
}
|
|
139
|
+
|
|
140
|
+
print("World background set to black")
|
|
141
|
+
"""
|
|
142
|
+
|
|
143
|
+
response = self.mcp.execute_code(generate_code())
|
|
144
|
+
# Extract the returned result from the MCP if available
|
|
145
|
+
if response.get("result") and isinstance(response["result"], dict):
|
|
146
|
+
return {"status": "success", **response["result"]}
|
|
147
|
+
# Add stdout to the response for debugging
|
|
148
|
+
if "stdout" in response:
|
|
149
|
+
return {"status": "success", "message": response.get("stdout", "")}
|
|
150
|
+
# Fallback
|
|
151
|
+
return {"status": "success"}
|
|
152
|
+
|
|
153
|
+
|
|
154
|
+
def generate_scene_diagnosis_code() -> str:
|
|
155
|
+
"""
|
|
156
|
+
Generates Python code that provides comprehensive diagnostics about the current Blender scene.
|
|
157
|
+
This includes information about all objects, materials, and potential issues.
|
|
158
|
+
|
|
159
|
+
Returns:
|
|
160
|
+
String containing Python code that can be executed in Blender
|
|
161
|
+
"""
|
|
162
|
+
code = """
|
|
163
|
+
import bpy
|
|
164
|
+
|
|
165
|
+
result = {"status": "processing", "objects": []}
|
|
166
|
+
|
|
167
|
+
# Get all objects in the scene
|
|
168
|
+
for obj in bpy.data.objects:
|
|
169
|
+
obj_info = {
|
|
170
|
+
"name": obj.name,
|
|
171
|
+
"type": obj.type,
|
|
172
|
+
"visible": obj.visible_get(),
|
|
173
|
+
"location": list(obj.location),
|
|
174
|
+
"scale": list(obj.scale),
|
|
175
|
+
"material_slots": len(obj.material_slots),
|
|
176
|
+
"has_materials": len(obj.material_slots) > 0 and obj.active_material is not None
|
|
177
|
+
}
|
|
178
|
+
|
|
179
|
+
# Add material info if available
|
|
180
|
+
if obj.active_material:
|
|
181
|
+
obj_info["active_material"] = {
|
|
182
|
+
"name": obj.active_material.name,
|
|
183
|
+
"has_diffuse_color": hasattr(obj.active_material, "diffuse_color"),
|
|
184
|
+
}
|
|
185
|
+
if hasattr(obj.active_material, "diffuse_color"):
|
|
186
|
+
obj_info["active_material"]["diffuse_color"] = list(obj.active_material.diffuse_color)
|
|
187
|
+
|
|
188
|
+
result["objects"].append(obj_info)
|
|
189
|
+
|
|
190
|
+
# Add overall scene info
|
|
191
|
+
result["object_count"] = len(result["objects"])
|
|
192
|
+
result["material_count"] = len(bpy.data.materials)
|
|
193
|
+
|
|
194
|
+
# Check for common issues
|
|
195
|
+
result["issues"] = []
|
|
196
|
+
|
|
197
|
+
# Check for objects without materials that typically need them
|
|
198
|
+
for obj in result["objects"]:
|
|
199
|
+
if obj["type"] in ["MESH", "CURVE", "SURFACE", "META", "FONT"] and not obj.get("has_materials", False):
|
|
200
|
+
result["issues"].append({
|
|
201
|
+
"type": "missing_material",
|
|
202
|
+
"object": obj["name"],
|
|
203
|
+
"message": f"Object '{obj['name']}' has no material assigned"
|
|
204
|
+
})
|
|
205
|
+
|
|
206
|
+
# Check for objects with unusual scales (potentially errors)
|
|
207
|
+
for obj in result["objects"]:
|
|
208
|
+
scales = obj.get("scale", [1, 1, 1])
|
|
209
|
+
if any(s < 0.0001 or s > 1000 for s in scales):
|
|
210
|
+
result["issues"].append({
|
|
211
|
+
"type": "unusual_scale",
|
|
212
|
+
"object": obj["name"],
|
|
213
|
+
"scale": scales,
|
|
214
|
+
"message": f"Object '{obj['name']}' has unusual scale: {scales}"
|
|
215
|
+
})
|
|
216
|
+
|
|
217
|
+
result["status"] = "success"
|
|
218
|
+
result
|
|
219
|
+
"""
|
|
220
|
+
return code
|