amd-gaia 0.15.0__py3-none-any.whl → 0.15.2__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.2.dist-info}/METADATA +222 -223
- amd_gaia-0.15.2.dist-info/RECORD +182 -0
- {amd_gaia-0.15.0.dist-info → amd_gaia-0.15.2.dist-info}/WHEEL +1 -1
- {amd_gaia-0.15.0.dist-info → amd_gaia-0.15.2.dist-info}/entry_points.txt +1 -0
- {amd_gaia-0.15.0.dist-info → amd_gaia-0.15.2.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 +2132 -2177
- gaia/agents/base/api_agent.py +119 -120
- gaia/agents/base/console.py +1967 -1841
- gaia/agents/base/errors.py +237 -237
- gaia/agents/base/mcp_agent.py +86 -86
- gaia/agents/base/tools.py +88 -83
- gaia/agents/blender/__init__.py +7 -0
- gaia/agents/blender/agent.py +553 -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 +809 -835
- gaia/agents/chat/app.py +1065 -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 +1744 -1729
- gaia/agents/chat/tools/shell_tools.py +437 -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 +2034 -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 +643 -642
- gaia/agents/emr/__init__.py +8 -8
- gaia/agents/emr/agent.py +1504 -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 +1972 -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 +184 -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 +428 -430
- gaia/chat/prompts.py +522 -522
- gaia/chat/sdk.py +1228 -1225
- gaia/cli.py +5659 -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/installer/__init__.py +23 -0
- gaia/installer/init_command.py +1275 -0
- gaia/installer/lemonade_installer.py +619 -0
- gaia/llm/__init__.py +10 -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 +3421 -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 +118 -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 +183 -163
- gaia/talk/app.py +287 -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.2.dist-info}/top_level.txt +0 -0
|
@@ -1,145 +1,145 @@
|
|
|
1
|
-
#!/usr/bin/env python
|
|
2
|
-
# Copyright(C) 2024-2025 Advanced Micro Devices, Inc. All rights reserved.
|
|
3
|
-
# SPDX-License-Identifier: MIT
|
|
4
|
-
"""Requirements.txt validation to detect hallucinated packages."""
|
|
5
|
-
|
|
6
|
-
import re
|
|
7
|
-
from pathlib import Path
|
|
8
|
-
from typing import Any, Dict, List
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
class RequirementsValidator:
|
|
12
|
-
"""Validates requirements.txt files for hallucinated packages."""
|
|
13
|
-
|
|
14
|
-
# Patterns indicating hallucinated packages
|
|
15
|
-
HALLUCINATION_PATTERNS = [
|
|
16
|
-
r".*-ibm-cloud-ibm-cloud.*", # Recursive IBM
|
|
17
|
-
r".*-azure-.*-azure.*", # Recursive Azure
|
|
18
|
-
r".*-gcp-.*-gcp.*", # Recursive GCP
|
|
19
|
-
r".*(\\w{4,})-\\1-\\1.*", # Same word 3+ times
|
|
20
|
-
r"flask-graphql-.*-.*-.*-.*-.*", # 5+ segments
|
|
21
|
-
]
|
|
22
|
-
|
|
23
|
-
def validate(self, req_file: Path, fix: bool = False) -> Dict[str, Any]:
|
|
24
|
-
"""Validate requirements.txt for hallucinated packages.
|
|
25
|
-
|
|
26
|
-
Args:
|
|
27
|
-
req_file: Path to requirements.txt file
|
|
28
|
-
fix: Whether to auto-fix issues
|
|
29
|
-
|
|
30
|
-
Returns:
|
|
31
|
-
Dictionary with validation results
|
|
32
|
-
"""
|
|
33
|
-
content = req_file.read_text()
|
|
34
|
-
errors = []
|
|
35
|
-
warnings = []
|
|
36
|
-
lines = content.strip().split("\n")
|
|
37
|
-
valid_lines = []
|
|
38
|
-
seen_packages = set()
|
|
39
|
-
|
|
40
|
-
for line_num, line in enumerate(lines, 1):
|
|
41
|
-
line = line.strip()
|
|
42
|
-
if not line or line.startswith("#"):
|
|
43
|
-
valid_lines.append(line)
|
|
44
|
-
continue
|
|
45
|
-
|
|
46
|
-
# Extract package name
|
|
47
|
-
package_match = re.match(r"^([a-zA-Z0-9][a-zA-Z0-9._-]*)", line)
|
|
48
|
-
if not package_match:
|
|
49
|
-
errors.append(f"Line {line_num}: Invalid format")
|
|
50
|
-
continue
|
|
51
|
-
|
|
52
|
-
package_name = package_match.group(1).lower()
|
|
53
|
-
|
|
54
|
-
# Check for hallucination
|
|
55
|
-
is_hallucinated = False
|
|
56
|
-
for pattern in self.HALLUCINATION_PATTERNS:
|
|
57
|
-
if re.match(pattern, package_name):
|
|
58
|
-
errors.append(
|
|
59
|
-
f"Line {line_num}: Hallucinated package: {package_name[:50]}..."
|
|
60
|
-
)
|
|
61
|
-
is_hallucinated = True
|
|
62
|
-
break
|
|
63
|
-
|
|
64
|
-
if is_hallucinated:
|
|
65
|
-
continue
|
|
66
|
-
|
|
67
|
-
# Check for excessive length
|
|
68
|
-
if len(package_name) > 60:
|
|
69
|
-
errors.append(
|
|
70
|
-
f"Line {line_num}: Package name too long ({len(package_name)} chars)"
|
|
71
|
-
)
|
|
72
|
-
continue
|
|
73
|
-
|
|
74
|
-
# Check duplicates
|
|
75
|
-
if package_name in seen_packages:
|
|
76
|
-
warnings.append(f"Line {line_num}: Duplicate package: {package_name}")
|
|
77
|
-
continue
|
|
78
|
-
|
|
79
|
-
seen_packages.add(package_name)
|
|
80
|
-
valid_lines.append(line)
|
|
81
|
-
|
|
82
|
-
# Check total count
|
|
83
|
-
if len(seen_packages) > 50:
|
|
84
|
-
errors.append(
|
|
85
|
-
f"Too many packages ({len(seen_packages)}). Likely hallucinated."
|
|
86
|
-
)
|
|
87
|
-
elif len(seen_packages) > 30:
|
|
88
|
-
warnings.append(f"Many packages ({len(seen_packages)})")
|
|
89
|
-
|
|
90
|
-
# Auto-fix if requested
|
|
91
|
-
fixed_content = None
|
|
92
|
-
if fix and errors:
|
|
93
|
-
fixed_content = "\n".join(valid_lines)
|
|
94
|
-
req_file.write_text(fixed_content)
|
|
95
|
-
|
|
96
|
-
return {
|
|
97
|
-
"is_valid": len(errors) == 0,
|
|
98
|
-
"errors": errors,
|
|
99
|
-
"warnings": warnings,
|
|
100
|
-
"packages": len(seen_packages),
|
|
101
|
-
"fixed_content": fixed_content,
|
|
102
|
-
}
|
|
103
|
-
|
|
104
|
-
def check_package_validity(self, package_name: str) -> bool:
|
|
105
|
-
"""Check if a package name appears valid.
|
|
106
|
-
|
|
107
|
-
Args:
|
|
108
|
-
package_name: Name of the package to check
|
|
109
|
-
|
|
110
|
-
Returns:
|
|
111
|
-
True if package name appears valid
|
|
112
|
-
"""
|
|
113
|
-
# Check against hallucination patterns
|
|
114
|
-
for pattern in self.HALLUCINATION_PATTERNS:
|
|
115
|
-
if re.match(pattern, package_name.lower()):
|
|
116
|
-
return False
|
|
117
|
-
|
|
118
|
-
# Check length
|
|
119
|
-
if len(package_name) > 60:
|
|
120
|
-
return False
|
|
121
|
-
|
|
122
|
-
# Check for valid characters
|
|
123
|
-
if not re.match(r"^[a-zA-Z0-9][a-zA-Z0-9._-]*$", package_name):
|
|
124
|
-
return False
|
|
125
|
-
|
|
126
|
-
return True
|
|
127
|
-
|
|
128
|
-
def suggest_common_packages(self, project_type: str) -> List[str]:
|
|
129
|
-
"""Suggest common packages for a project type.
|
|
130
|
-
|
|
131
|
-
Args:
|
|
132
|
-
project_type: Type of project (e.g., 'web', 'data', 'ml')
|
|
133
|
-
|
|
134
|
-
Returns:
|
|
135
|
-
List of suggested package names
|
|
136
|
-
"""
|
|
137
|
-
suggestions = {
|
|
138
|
-
"web": ["flask", "django", "fastapi", "requests", "beautifulsoup4"],
|
|
139
|
-
"data": ["pandas", "numpy", "matplotlib", "seaborn", "jupyter"],
|
|
140
|
-
"ml": ["scikit-learn", "tensorflow", "torch", "transformers", "datasets"],
|
|
141
|
-
"test": ["pytest", "pytest-cov", "mock", "hypothesis", "tox"],
|
|
142
|
-
"general": ["black", "pylint", "mypy", "python-dotenv", "pyyaml"],
|
|
143
|
-
}
|
|
144
|
-
|
|
145
|
-
return suggestions.get(project_type, suggestions["general"])
|
|
1
|
+
#!/usr/bin/env python
|
|
2
|
+
# Copyright(C) 2024-2025 Advanced Micro Devices, Inc. All rights reserved.
|
|
3
|
+
# SPDX-License-Identifier: MIT
|
|
4
|
+
"""Requirements.txt validation to detect hallucinated packages."""
|
|
5
|
+
|
|
6
|
+
import re
|
|
7
|
+
from pathlib import Path
|
|
8
|
+
from typing import Any, Dict, List
|
|
9
|
+
|
|
10
|
+
|
|
11
|
+
class RequirementsValidator:
|
|
12
|
+
"""Validates requirements.txt files for hallucinated packages."""
|
|
13
|
+
|
|
14
|
+
# Patterns indicating hallucinated packages
|
|
15
|
+
HALLUCINATION_PATTERNS = [
|
|
16
|
+
r".*-ibm-cloud-ibm-cloud.*", # Recursive IBM
|
|
17
|
+
r".*-azure-.*-azure.*", # Recursive Azure
|
|
18
|
+
r".*-gcp-.*-gcp.*", # Recursive GCP
|
|
19
|
+
r".*(\\w{4,})-\\1-\\1.*", # Same word 3+ times
|
|
20
|
+
r"flask-graphql-.*-.*-.*-.*-.*", # 5+ segments
|
|
21
|
+
]
|
|
22
|
+
|
|
23
|
+
def validate(self, req_file: Path, fix: bool = False) -> Dict[str, Any]:
|
|
24
|
+
"""Validate requirements.txt for hallucinated packages.
|
|
25
|
+
|
|
26
|
+
Args:
|
|
27
|
+
req_file: Path to requirements.txt file
|
|
28
|
+
fix: Whether to auto-fix issues
|
|
29
|
+
|
|
30
|
+
Returns:
|
|
31
|
+
Dictionary with validation results
|
|
32
|
+
"""
|
|
33
|
+
content = req_file.read_text()
|
|
34
|
+
errors = []
|
|
35
|
+
warnings = []
|
|
36
|
+
lines = content.strip().split("\n")
|
|
37
|
+
valid_lines = []
|
|
38
|
+
seen_packages = set()
|
|
39
|
+
|
|
40
|
+
for line_num, line in enumerate(lines, 1):
|
|
41
|
+
line = line.strip()
|
|
42
|
+
if not line or line.startswith("#"):
|
|
43
|
+
valid_lines.append(line)
|
|
44
|
+
continue
|
|
45
|
+
|
|
46
|
+
# Extract package name
|
|
47
|
+
package_match = re.match(r"^([a-zA-Z0-9][a-zA-Z0-9._-]*)", line)
|
|
48
|
+
if not package_match:
|
|
49
|
+
errors.append(f"Line {line_num}: Invalid format")
|
|
50
|
+
continue
|
|
51
|
+
|
|
52
|
+
package_name = package_match.group(1).lower()
|
|
53
|
+
|
|
54
|
+
# Check for hallucination
|
|
55
|
+
is_hallucinated = False
|
|
56
|
+
for pattern in self.HALLUCINATION_PATTERNS:
|
|
57
|
+
if re.match(pattern, package_name):
|
|
58
|
+
errors.append(
|
|
59
|
+
f"Line {line_num}: Hallucinated package: {package_name[:50]}..."
|
|
60
|
+
)
|
|
61
|
+
is_hallucinated = True
|
|
62
|
+
break
|
|
63
|
+
|
|
64
|
+
if is_hallucinated:
|
|
65
|
+
continue
|
|
66
|
+
|
|
67
|
+
# Check for excessive length
|
|
68
|
+
if len(package_name) > 60:
|
|
69
|
+
errors.append(
|
|
70
|
+
f"Line {line_num}: Package name too long ({len(package_name)} chars)"
|
|
71
|
+
)
|
|
72
|
+
continue
|
|
73
|
+
|
|
74
|
+
# Check duplicates
|
|
75
|
+
if package_name in seen_packages:
|
|
76
|
+
warnings.append(f"Line {line_num}: Duplicate package: {package_name}")
|
|
77
|
+
continue
|
|
78
|
+
|
|
79
|
+
seen_packages.add(package_name)
|
|
80
|
+
valid_lines.append(line)
|
|
81
|
+
|
|
82
|
+
# Check total count
|
|
83
|
+
if len(seen_packages) > 50:
|
|
84
|
+
errors.append(
|
|
85
|
+
f"Too many packages ({len(seen_packages)}). Likely hallucinated."
|
|
86
|
+
)
|
|
87
|
+
elif len(seen_packages) > 30:
|
|
88
|
+
warnings.append(f"Many packages ({len(seen_packages)})")
|
|
89
|
+
|
|
90
|
+
# Auto-fix if requested
|
|
91
|
+
fixed_content = None
|
|
92
|
+
if fix and errors:
|
|
93
|
+
fixed_content = "\n".join(valid_lines)
|
|
94
|
+
req_file.write_text(fixed_content)
|
|
95
|
+
|
|
96
|
+
return {
|
|
97
|
+
"is_valid": len(errors) == 0,
|
|
98
|
+
"errors": errors,
|
|
99
|
+
"warnings": warnings,
|
|
100
|
+
"packages": len(seen_packages),
|
|
101
|
+
"fixed_content": fixed_content,
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
def check_package_validity(self, package_name: str) -> bool:
|
|
105
|
+
"""Check if a package name appears valid.
|
|
106
|
+
|
|
107
|
+
Args:
|
|
108
|
+
package_name: Name of the package to check
|
|
109
|
+
|
|
110
|
+
Returns:
|
|
111
|
+
True if package name appears valid
|
|
112
|
+
"""
|
|
113
|
+
# Check against hallucination patterns
|
|
114
|
+
for pattern in self.HALLUCINATION_PATTERNS:
|
|
115
|
+
if re.match(pattern, package_name.lower()):
|
|
116
|
+
return False
|
|
117
|
+
|
|
118
|
+
# Check length
|
|
119
|
+
if len(package_name) > 60:
|
|
120
|
+
return False
|
|
121
|
+
|
|
122
|
+
# Check for valid characters
|
|
123
|
+
if not re.match(r"^[a-zA-Z0-9][a-zA-Z0-9._-]*$", package_name):
|
|
124
|
+
return False
|
|
125
|
+
|
|
126
|
+
return True
|
|
127
|
+
|
|
128
|
+
def suggest_common_packages(self, project_type: str) -> List[str]:
|
|
129
|
+
"""Suggest common packages for a project type.
|
|
130
|
+
|
|
131
|
+
Args:
|
|
132
|
+
project_type: Type of project (e.g., 'web', 'data', 'ml')
|
|
133
|
+
|
|
134
|
+
Returns:
|
|
135
|
+
List of suggested package names
|
|
136
|
+
"""
|
|
137
|
+
suggestions = {
|
|
138
|
+
"web": ["flask", "django", "fastapi", "requests", "beautifulsoup4"],
|
|
139
|
+
"data": ["pandas", "numpy", "matplotlib", "seaborn", "jupyter"],
|
|
140
|
+
"ml": ["scikit-learn", "tensorflow", "torch", "transformers", "datasets"],
|
|
141
|
+
"test": ["pytest", "pytest-cov", "mock", "hypothesis", "tox"],
|
|
142
|
+
"general": ["black", "pylint", "mypy", "python-dotenv", "pyyaml"],
|
|
143
|
+
}
|
|
144
|
+
|
|
145
|
+
return suggestions.get(project_type, suggestions["general"])
|
|
@@ -1,171 +1,171 @@
|
|
|
1
|
-
#!/usr/bin/env python
|
|
2
|
-
# Copyright(C) 2024-2025 Advanced Micro Devices, Inc. All rights reserved.
|
|
3
|
-
# SPDX-License-Identifier: MIT
|
|
4
|
-
"""Python syntax validation module."""
|
|
5
|
-
|
|
6
|
-
import ast
|
|
7
|
-
from typing import Any, Dict, List
|
|
8
|
-
|
|
9
|
-
from ..models import ValidationResult
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
class SyntaxValidator:
|
|
13
|
-
"""Validates Python code syntax."""
|
|
14
|
-
|
|
15
|
-
def validate(self, code: str) -> ValidationResult:
|
|
16
|
-
"""Validate Python code syntax.
|
|
17
|
-
|
|
18
|
-
Args:
|
|
19
|
-
code: Python code to validate
|
|
20
|
-
|
|
21
|
-
Returns:
|
|
22
|
-
ValidationResult with validation details
|
|
23
|
-
"""
|
|
24
|
-
result = ValidationResult(is_valid=True)
|
|
25
|
-
|
|
26
|
-
try:
|
|
27
|
-
# Try to compile the code
|
|
28
|
-
compile(code, "<string>", "exec")
|
|
29
|
-
|
|
30
|
-
# Also try to parse with AST for more detailed checking
|
|
31
|
-
ast.parse(code)
|
|
32
|
-
|
|
33
|
-
return result
|
|
34
|
-
|
|
35
|
-
except SyntaxError as e:
|
|
36
|
-
result.is_valid = False
|
|
37
|
-
result.errors.append(f"Line {e.lineno}: {e.msg}")
|
|
38
|
-
if e.text:
|
|
39
|
-
result.errors.append(f" {e.text.rstrip()}")
|
|
40
|
-
if e.offset:
|
|
41
|
-
result.errors.append(f" {' ' * (e.offset - 1)}^")
|
|
42
|
-
return result
|
|
43
|
-
|
|
44
|
-
except Exception as e:
|
|
45
|
-
result.is_valid = False
|
|
46
|
-
result.errors.append(f"Parse error: {str(e)}")
|
|
47
|
-
return result
|
|
48
|
-
|
|
49
|
-
def validate_dict(self, code: str) -> Dict[str, Any]:
|
|
50
|
-
"""Validate Python code and return as dictionary (legacy format).
|
|
51
|
-
|
|
52
|
-
Args:
|
|
53
|
-
code: Python code to validate
|
|
54
|
-
|
|
55
|
-
Returns:
|
|
56
|
-
Dictionary with validation results
|
|
57
|
-
"""
|
|
58
|
-
result = self.validate(code)
|
|
59
|
-
|
|
60
|
-
return {
|
|
61
|
-
"status": "success" if result.is_valid else "error",
|
|
62
|
-
"is_valid": result.is_valid,
|
|
63
|
-
"errors": result.errors,
|
|
64
|
-
"message": "Syntax is valid" if result.is_valid else "Syntax errors found",
|
|
65
|
-
}
|
|
66
|
-
|
|
67
|
-
def get_syntax_errors(self, code: str) -> List[SyntaxError]:
|
|
68
|
-
"""Get all syntax errors from code.
|
|
69
|
-
|
|
70
|
-
Args:
|
|
71
|
-
code: Python code to check
|
|
72
|
-
|
|
73
|
-
Returns:
|
|
74
|
-
List of SyntaxError objects
|
|
75
|
-
"""
|
|
76
|
-
errors = []
|
|
77
|
-
try:
|
|
78
|
-
compile(code, "<string>", "exec")
|
|
79
|
-
except SyntaxError as e:
|
|
80
|
-
errors.append(e)
|
|
81
|
-
|
|
82
|
-
return errors
|
|
83
|
-
|
|
84
|
-
def check_indentation(self, code: str) -> List[str]:
|
|
85
|
-
"""Check for indentation issues in code.
|
|
86
|
-
|
|
87
|
-
Args:
|
|
88
|
-
code: Python code to check
|
|
89
|
-
|
|
90
|
-
Returns:
|
|
91
|
-
List of indentation warnings
|
|
92
|
-
"""
|
|
93
|
-
warnings = []
|
|
94
|
-
lines = code.split("\n")
|
|
95
|
-
|
|
96
|
-
for i, line in enumerate(lines, 1):
|
|
97
|
-
if line and line[0] in " \t":
|
|
98
|
-
# Check for mixed tabs and spaces
|
|
99
|
-
if " " in line and "\t" in line:
|
|
100
|
-
warnings.append(f"Line {i}: Mixed tabs and spaces in indentation")
|
|
101
|
-
|
|
102
|
-
# Check for non-standard indentation (not multiples of 4)
|
|
103
|
-
if line.startswith(" "):
|
|
104
|
-
spaces = len(line) - len(line.lstrip())
|
|
105
|
-
if spaces % 4 != 0:
|
|
106
|
-
warnings.append(
|
|
107
|
-
f"Line {i}: Non-standard indentation ({spaces} spaces)"
|
|
108
|
-
)
|
|
109
|
-
|
|
110
|
-
return warnings
|
|
111
|
-
|
|
112
|
-
def validate_imports(self, code: str) -> List[str]:
|
|
113
|
-
"""Validate import statements in code.
|
|
114
|
-
|
|
115
|
-
Args:
|
|
116
|
-
code: Python code to check
|
|
117
|
-
|
|
118
|
-
Returns:
|
|
119
|
-
List of import-related warnings
|
|
120
|
-
"""
|
|
121
|
-
warnings = []
|
|
122
|
-
|
|
123
|
-
try:
|
|
124
|
-
tree = ast.parse(code)
|
|
125
|
-
|
|
126
|
-
# Check for wildcard imports
|
|
127
|
-
for node in ast.walk(tree):
|
|
128
|
-
if isinstance(node, ast.ImportFrom):
|
|
129
|
-
for alias in node.names:
|
|
130
|
-
if alias.name == "*":
|
|
131
|
-
warnings.append(
|
|
132
|
-
f"Line {node.lineno}: Wildcard import 'from {node.module} import *' is discouraged"
|
|
133
|
-
)
|
|
134
|
-
|
|
135
|
-
# Check for duplicate imports
|
|
136
|
-
imports_seen = set()
|
|
137
|
-
for node in ast.walk(tree):
|
|
138
|
-
if isinstance(node, ast.Import):
|
|
139
|
-
for alias in node.names:
|
|
140
|
-
if alias.name in imports_seen:
|
|
141
|
-
warnings.append(
|
|
142
|
-
f"Line {node.lineno}: Duplicate import '{alias.name}'"
|
|
143
|
-
)
|
|
144
|
-
imports_seen.add(alias.name)
|
|
145
|
-
|
|
146
|
-
except SyntaxError:
|
|
147
|
-
# Syntax errors will be caught by main validation
|
|
148
|
-
pass
|
|
149
|
-
|
|
150
|
-
return warnings
|
|
151
|
-
|
|
152
|
-
def check_line_length(self, code: str, max_length: int = 88) -> List[str]:
|
|
153
|
-
"""Check for lines exceeding maximum length.
|
|
154
|
-
|
|
155
|
-
Args:
|
|
156
|
-
code: Python code to check
|
|
157
|
-
max_length: Maximum allowed line length (default: 88 for Black)
|
|
158
|
-
|
|
159
|
-
Returns:
|
|
160
|
-
List of line length warnings
|
|
161
|
-
"""
|
|
162
|
-
warnings = []
|
|
163
|
-
lines = code.split("\n")
|
|
164
|
-
|
|
165
|
-
for i, line in enumerate(lines, 1):
|
|
166
|
-
if len(line) > max_length:
|
|
167
|
-
warnings.append(
|
|
168
|
-
f"Line {i}: Line too long ({len(line)} > {max_length} characters)"
|
|
169
|
-
)
|
|
170
|
-
|
|
171
|
-
return warnings
|
|
1
|
+
#!/usr/bin/env python
|
|
2
|
+
# Copyright(C) 2024-2025 Advanced Micro Devices, Inc. All rights reserved.
|
|
3
|
+
# SPDX-License-Identifier: MIT
|
|
4
|
+
"""Python syntax validation module."""
|
|
5
|
+
|
|
6
|
+
import ast
|
|
7
|
+
from typing import Any, Dict, List
|
|
8
|
+
|
|
9
|
+
from ..models import ValidationResult
|
|
10
|
+
|
|
11
|
+
|
|
12
|
+
class SyntaxValidator:
|
|
13
|
+
"""Validates Python code syntax."""
|
|
14
|
+
|
|
15
|
+
def validate(self, code: str) -> ValidationResult:
|
|
16
|
+
"""Validate Python code syntax.
|
|
17
|
+
|
|
18
|
+
Args:
|
|
19
|
+
code: Python code to validate
|
|
20
|
+
|
|
21
|
+
Returns:
|
|
22
|
+
ValidationResult with validation details
|
|
23
|
+
"""
|
|
24
|
+
result = ValidationResult(is_valid=True)
|
|
25
|
+
|
|
26
|
+
try:
|
|
27
|
+
# Try to compile the code
|
|
28
|
+
compile(code, "<string>", "exec")
|
|
29
|
+
|
|
30
|
+
# Also try to parse with AST for more detailed checking
|
|
31
|
+
ast.parse(code)
|
|
32
|
+
|
|
33
|
+
return result
|
|
34
|
+
|
|
35
|
+
except SyntaxError as e:
|
|
36
|
+
result.is_valid = False
|
|
37
|
+
result.errors.append(f"Line {e.lineno}: {e.msg}")
|
|
38
|
+
if e.text:
|
|
39
|
+
result.errors.append(f" {e.text.rstrip()}")
|
|
40
|
+
if e.offset:
|
|
41
|
+
result.errors.append(f" {' ' * (e.offset - 1)}^")
|
|
42
|
+
return result
|
|
43
|
+
|
|
44
|
+
except Exception as e:
|
|
45
|
+
result.is_valid = False
|
|
46
|
+
result.errors.append(f"Parse error: {str(e)}")
|
|
47
|
+
return result
|
|
48
|
+
|
|
49
|
+
def validate_dict(self, code: str) -> Dict[str, Any]:
|
|
50
|
+
"""Validate Python code and return as dictionary (legacy format).
|
|
51
|
+
|
|
52
|
+
Args:
|
|
53
|
+
code: Python code to validate
|
|
54
|
+
|
|
55
|
+
Returns:
|
|
56
|
+
Dictionary with validation results
|
|
57
|
+
"""
|
|
58
|
+
result = self.validate(code)
|
|
59
|
+
|
|
60
|
+
return {
|
|
61
|
+
"status": "success" if result.is_valid else "error",
|
|
62
|
+
"is_valid": result.is_valid,
|
|
63
|
+
"errors": result.errors,
|
|
64
|
+
"message": "Syntax is valid" if result.is_valid else "Syntax errors found",
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
def get_syntax_errors(self, code: str) -> List[SyntaxError]:
|
|
68
|
+
"""Get all syntax errors from code.
|
|
69
|
+
|
|
70
|
+
Args:
|
|
71
|
+
code: Python code to check
|
|
72
|
+
|
|
73
|
+
Returns:
|
|
74
|
+
List of SyntaxError objects
|
|
75
|
+
"""
|
|
76
|
+
errors = []
|
|
77
|
+
try:
|
|
78
|
+
compile(code, "<string>", "exec")
|
|
79
|
+
except SyntaxError as e:
|
|
80
|
+
errors.append(e)
|
|
81
|
+
|
|
82
|
+
return errors
|
|
83
|
+
|
|
84
|
+
def check_indentation(self, code: str) -> List[str]:
|
|
85
|
+
"""Check for indentation issues in code.
|
|
86
|
+
|
|
87
|
+
Args:
|
|
88
|
+
code: Python code to check
|
|
89
|
+
|
|
90
|
+
Returns:
|
|
91
|
+
List of indentation warnings
|
|
92
|
+
"""
|
|
93
|
+
warnings = []
|
|
94
|
+
lines = code.split("\n")
|
|
95
|
+
|
|
96
|
+
for i, line in enumerate(lines, 1):
|
|
97
|
+
if line and line[0] in " \t":
|
|
98
|
+
# Check for mixed tabs and spaces
|
|
99
|
+
if " " in line and "\t" in line:
|
|
100
|
+
warnings.append(f"Line {i}: Mixed tabs and spaces in indentation")
|
|
101
|
+
|
|
102
|
+
# Check for non-standard indentation (not multiples of 4)
|
|
103
|
+
if line.startswith(" "):
|
|
104
|
+
spaces = len(line) - len(line.lstrip())
|
|
105
|
+
if spaces % 4 != 0:
|
|
106
|
+
warnings.append(
|
|
107
|
+
f"Line {i}: Non-standard indentation ({spaces} spaces)"
|
|
108
|
+
)
|
|
109
|
+
|
|
110
|
+
return warnings
|
|
111
|
+
|
|
112
|
+
def validate_imports(self, code: str) -> List[str]:
|
|
113
|
+
"""Validate import statements in code.
|
|
114
|
+
|
|
115
|
+
Args:
|
|
116
|
+
code: Python code to check
|
|
117
|
+
|
|
118
|
+
Returns:
|
|
119
|
+
List of import-related warnings
|
|
120
|
+
"""
|
|
121
|
+
warnings = []
|
|
122
|
+
|
|
123
|
+
try:
|
|
124
|
+
tree = ast.parse(code)
|
|
125
|
+
|
|
126
|
+
# Check for wildcard imports
|
|
127
|
+
for node in ast.walk(tree):
|
|
128
|
+
if isinstance(node, ast.ImportFrom):
|
|
129
|
+
for alias in node.names:
|
|
130
|
+
if alias.name == "*":
|
|
131
|
+
warnings.append(
|
|
132
|
+
f"Line {node.lineno}: Wildcard import 'from {node.module} import *' is discouraged"
|
|
133
|
+
)
|
|
134
|
+
|
|
135
|
+
# Check for duplicate imports
|
|
136
|
+
imports_seen = set()
|
|
137
|
+
for node in ast.walk(tree):
|
|
138
|
+
if isinstance(node, ast.Import):
|
|
139
|
+
for alias in node.names:
|
|
140
|
+
if alias.name in imports_seen:
|
|
141
|
+
warnings.append(
|
|
142
|
+
f"Line {node.lineno}: Duplicate import '{alias.name}'"
|
|
143
|
+
)
|
|
144
|
+
imports_seen.add(alias.name)
|
|
145
|
+
|
|
146
|
+
except SyntaxError:
|
|
147
|
+
# Syntax errors will be caught by main validation
|
|
148
|
+
pass
|
|
149
|
+
|
|
150
|
+
return warnings
|
|
151
|
+
|
|
152
|
+
def check_line_length(self, code: str, max_length: int = 88) -> List[str]:
|
|
153
|
+
"""Check for lines exceeding maximum length.
|
|
154
|
+
|
|
155
|
+
Args:
|
|
156
|
+
code: Python code to check
|
|
157
|
+
max_length: Maximum allowed line length (default: 88 for Black)
|
|
158
|
+
|
|
159
|
+
Returns:
|
|
160
|
+
List of line length warnings
|
|
161
|
+
"""
|
|
162
|
+
warnings = []
|
|
163
|
+
lines = code.split("\n")
|
|
164
|
+
|
|
165
|
+
for i, line in enumerate(lines, 1):
|
|
166
|
+
if len(line) > max_length:
|
|
167
|
+
warnings.append(
|
|
168
|
+
f"Line {i}: Line too long ({len(line)} > {max_length} characters)"
|
|
169
|
+
)
|
|
170
|
+
|
|
171
|
+
return warnings
|
gaia/agents/docker/__init__.py
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
|
-
# Copyright(C) 2025-2026 Advanced Micro Devices, Inc. All rights reserved.
|
|
2
|
-
# SPDX-License-Identifier: MIT
|
|
3
|
-
"""Docker agent for GAIA."""
|
|
4
|
-
|
|
5
|
-
from gaia.agents.docker.agent import DockerAgent
|
|
6
|
-
|
|
7
|
-
__all__ = ["DockerAgent"]
|
|
1
|
+
# Copyright(C) 2025-2026 Advanced Micro Devices, Inc. All rights reserved.
|
|
2
|
+
# SPDX-License-Identifier: MIT
|
|
3
|
+
"""Docker agent for GAIA."""
|
|
4
|
+
|
|
5
|
+
from gaia.agents.docker.agent import DockerAgent
|
|
6
|
+
|
|
7
|
+
__all__ = ["DockerAgent"]
|