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,190 +1,190 @@
|
|
|
1
|
-
# Copyright(C) 2025-2026 Advanced Micro Devices, Inc. All rights reserved.
|
|
2
|
-
# SPDX-License-Identifier: MIT
|
|
3
|
-
"""Prisma database tools for Code Agent.
|
|
4
|
-
|
|
5
|
-
This mixin provides tools for managing Prisma database setup and operations,
|
|
6
|
-
enforcing the correct workflow to prevent common errors.
|
|
7
|
-
"""
|
|
8
|
-
|
|
9
|
-
import logging
|
|
10
|
-
import subprocess
|
|
11
|
-
from pathlib import Path
|
|
12
|
-
from typing import Any, Dict
|
|
13
|
-
|
|
14
|
-
from gaia.agents.base.tools import tool
|
|
15
|
-
|
|
16
|
-
logger = logging.getLogger(__name__)
|
|
17
|
-
|
|
18
|
-
# Prisma singleton template for Next.js (prevents connection pool exhaustion)
|
|
19
|
-
PRISMA_SINGLETON_TEMPLATE = """// Copyright(C) 2024-2025 Advanced Micro Devices, Inc. All rights reserved.
|
|
20
|
-
// SPDX-License-Identifier: MIT
|
|
21
|
-
import { PrismaClient } from "@prisma/client";
|
|
22
|
-
|
|
23
|
-
const globalForPrisma = globalThis as unknown as {
|
|
24
|
-
prisma: PrismaClient | undefined;
|
|
25
|
-
};
|
|
26
|
-
|
|
27
|
-
export const prisma = globalForPrisma.prisma ?? new PrismaClient();
|
|
28
|
-
|
|
29
|
-
if (process.env.NODE_ENV !== "production") {
|
|
30
|
-
globalForPrisma.prisma = prisma;
|
|
31
|
-
}
|
|
32
|
-
"""
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
class PrismaToolsMixin:
|
|
36
|
-
"""Mixin providing Prisma database management tools for the Code Agent."""
|
|
37
|
-
|
|
38
|
-
def register_prisma_tools(self) -> None:
|
|
39
|
-
"""Register Prisma database tools with the agent."""
|
|
40
|
-
|
|
41
|
-
@tool
|
|
42
|
-
def setup_prisma(
|
|
43
|
-
project_dir: str,
|
|
44
|
-
regenerate: bool = True,
|
|
45
|
-
push_db: bool = True,
|
|
46
|
-
) -> Dict[str, Any]:
|
|
47
|
-
"""Set up or update Prisma client after schema changes.
|
|
48
|
-
|
|
49
|
-
This tool enforces the correct Prisma workflow:
|
|
50
|
-
1. Generates Prisma Client (TypeScript types)
|
|
51
|
-
2. Pushes schema to database
|
|
52
|
-
3. Verifies the singleton file exists
|
|
53
|
-
4. Returns the correct import paths to use
|
|
54
|
-
|
|
55
|
-
Call this tool:
|
|
56
|
-
- After creating or modifying prisma/schema.prisma
|
|
57
|
-
- When you see "Cannot find name 'Todo'" or similar type errors
|
|
58
|
-
- When you see "Module '@prisma/client' has no exported member" errors
|
|
59
|
-
|
|
60
|
-
Args:
|
|
61
|
-
project_dir: Path to the Next.js project directory
|
|
62
|
-
regenerate: Whether to run prisma generate (default: True)
|
|
63
|
-
push_db: Whether to run prisma db push (default: True)
|
|
64
|
-
|
|
65
|
-
Returns:
|
|
66
|
-
Dictionary with:
|
|
67
|
-
- success: bool
|
|
68
|
-
- generated: bool (whether prisma generate ran)
|
|
69
|
-
- pushed: bool (whether prisma db push ran)
|
|
70
|
-
- singleton_path: str (path to singleton file)
|
|
71
|
-
- import_patterns: dict (correct import statements to use)
|
|
72
|
-
- output: str (command output)
|
|
73
|
-
- error: str (if failed)
|
|
74
|
-
"""
|
|
75
|
-
try:
|
|
76
|
-
project_path = Path(project_dir).resolve()
|
|
77
|
-
if not project_path.exists():
|
|
78
|
-
return {
|
|
79
|
-
"success": False,
|
|
80
|
-
"error": f"Project directory does not exist: {project_dir}",
|
|
81
|
-
"error_type": "validation_error",
|
|
82
|
-
}
|
|
83
|
-
|
|
84
|
-
schema_path = project_path / "prisma" / "schema.prisma"
|
|
85
|
-
if not schema_path.exists():
|
|
86
|
-
return {
|
|
87
|
-
"success": False,
|
|
88
|
-
"error": f"Prisma schema not found at {schema_path}. Run 'npx prisma init' first.",
|
|
89
|
-
"error_type": "schema_error",
|
|
90
|
-
}
|
|
91
|
-
|
|
92
|
-
output_lines = []
|
|
93
|
-
generated = False
|
|
94
|
-
pushed = False
|
|
95
|
-
|
|
96
|
-
# Step 1: Generate Prisma Client
|
|
97
|
-
if regenerate:
|
|
98
|
-
logger.info(f"Running prisma generate in {project_dir}")
|
|
99
|
-
result = subprocess.run(
|
|
100
|
-
["npx", "prisma", "generate"],
|
|
101
|
-
cwd=str(project_path),
|
|
102
|
-
capture_output=True,
|
|
103
|
-
text=True,
|
|
104
|
-
timeout=120,
|
|
105
|
-
check=False,
|
|
106
|
-
)
|
|
107
|
-
output_lines.append("=== prisma generate ===")
|
|
108
|
-
output_lines.append(result.stdout)
|
|
109
|
-
if result.stderr:
|
|
110
|
-
output_lines.append(result.stderr)
|
|
111
|
-
|
|
112
|
-
if result.returncode != 0:
|
|
113
|
-
return {
|
|
114
|
-
"success": False,
|
|
115
|
-
"generated": False,
|
|
116
|
-
"error": f"prisma generate failed: {result.stderr}",
|
|
117
|
-
"error_type": "client_error",
|
|
118
|
-
"output": "\n".join(output_lines),
|
|
119
|
-
}
|
|
120
|
-
generated = True
|
|
121
|
-
|
|
122
|
-
# Step 2: Push schema to database
|
|
123
|
-
if push_db:
|
|
124
|
-
logger.info(f"Running prisma db push in {project_dir}")
|
|
125
|
-
result = subprocess.run(
|
|
126
|
-
["npx", "prisma", "db", "push"],
|
|
127
|
-
cwd=str(project_path),
|
|
128
|
-
capture_output=True,
|
|
129
|
-
text=True,
|
|
130
|
-
timeout=120,
|
|
131
|
-
check=False,
|
|
132
|
-
)
|
|
133
|
-
output_lines.append("\n=== prisma db push ===")
|
|
134
|
-
output_lines.append(result.stdout)
|
|
135
|
-
if result.stderr:
|
|
136
|
-
output_lines.append(result.stderr)
|
|
137
|
-
|
|
138
|
-
if result.returncode != 0:
|
|
139
|
-
return {
|
|
140
|
-
"success": False,
|
|
141
|
-
"generated": generated,
|
|
142
|
-
"pushed": False,
|
|
143
|
-
"error": f"prisma db push failed: {result.stderr}",
|
|
144
|
-
"error_type": "migration_error",
|
|
145
|
-
"output": "\n".join(output_lines),
|
|
146
|
-
}
|
|
147
|
-
pushed = True
|
|
148
|
-
|
|
149
|
-
# Step 3: Create singleton file if it doesn't exist
|
|
150
|
-
singleton_path = project_path / "src" / "lib" / "prisma.ts"
|
|
151
|
-
singleton_created = False
|
|
152
|
-
|
|
153
|
-
if not singleton_path.exists():
|
|
154
|
-
singleton_path.parent.mkdir(parents=True, exist_ok=True)
|
|
155
|
-
singleton_path.write_text(
|
|
156
|
-
PRISMA_SINGLETON_TEMPLATE, encoding="utf-8"
|
|
157
|
-
)
|
|
158
|
-
singleton_created = True
|
|
159
|
-
output_lines.append(
|
|
160
|
-
f"\nCreated Prisma singleton at {singleton_path}"
|
|
161
|
-
)
|
|
162
|
-
logger.info(f"Created Prisma singleton at {singleton_path}")
|
|
163
|
-
|
|
164
|
-
return {
|
|
165
|
-
"success": True,
|
|
166
|
-
"generated": generated,
|
|
167
|
-
"pushed": pushed,
|
|
168
|
-
"singleton_created": singleton_created,
|
|
169
|
-
"singleton_path": str(singleton_path.relative_to(project_path)),
|
|
170
|
-
"import_patterns": {
|
|
171
|
-
"client_instance": "import { prisma } from '@/lib/prisma'",
|
|
172
|
-
"model_types": "import { Todo, User } from '@prisma/client'",
|
|
173
|
-
"prisma_namespace": "import { Prisma } from '@prisma/client'",
|
|
174
|
-
},
|
|
175
|
-
"output": "\n".join(output_lines),
|
|
176
|
-
}
|
|
177
|
-
|
|
178
|
-
except subprocess.TimeoutExpired:
|
|
179
|
-
return {
|
|
180
|
-
"success": False,
|
|
181
|
-
"error": "Prisma command timed out (exceeded 120 seconds)",
|
|
182
|
-
"error_type": "runtime_error",
|
|
183
|
-
}
|
|
184
|
-
except Exception as e:
|
|
185
|
-
logger.error(f"Error in setup_prisma: {e}", exc_info=True)
|
|
186
|
-
return {
|
|
187
|
-
"success": False,
|
|
188
|
-
"error": str(e),
|
|
189
|
-
"error_type": "runtime_error",
|
|
190
|
-
}
|
|
1
|
+
# Copyright(C) 2025-2026 Advanced Micro Devices, Inc. All rights reserved.
|
|
2
|
+
# SPDX-License-Identifier: MIT
|
|
3
|
+
"""Prisma database tools for Code Agent.
|
|
4
|
+
|
|
5
|
+
This mixin provides tools for managing Prisma database setup and operations,
|
|
6
|
+
enforcing the correct workflow to prevent common errors.
|
|
7
|
+
"""
|
|
8
|
+
|
|
9
|
+
import logging
|
|
10
|
+
import subprocess
|
|
11
|
+
from pathlib import Path
|
|
12
|
+
from typing import Any, Dict
|
|
13
|
+
|
|
14
|
+
from gaia.agents.base.tools import tool
|
|
15
|
+
|
|
16
|
+
logger = logging.getLogger(__name__)
|
|
17
|
+
|
|
18
|
+
# Prisma singleton template for Next.js (prevents connection pool exhaustion)
|
|
19
|
+
PRISMA_SINGLETON_TEMPLATE = """// Copyright(C) 2024-2025 Advanced Micro Devices, Inc. All rights reserved.
|
|
20
|
+
// SPDX-License-Identifier: MIT
|
|
21
|
+
import { PrismaClient } from "@prisma/client";
|
|
22
|
+
|
|
23
|
+
const globalForPrisma = globalThis as unknown as {
|
|
24
|
+
prisma: PrismaClient | undefined;
|
|
25
|
+
};
|
|
26
|
+
|
|
27
|
+
export const prisma = globalForPrisma.prisma ?? new PrismaClient();
|
|
28
|
+
|
|
29
|
+
if (process.env.NODE_ENV !== "production") {
|
|
30
|
+
globalForPrisma.prisma = prisma;
|
|
31
|
+
}
|
|
32
|
+
"""
|
|
33
|
+
|
|
34
|
+
|
|
35
|
+
class PrismaToolsMixin:
|
|
36
|
+
"""Mixin providing Prisma database management tools for the Code Agent."""
|
|
37
|
+
|
|
38
|
+
def register_prisma_tools(self) -> None:
|
|
39
|
+
"""Register Prisma database tools with the agent."""
|
|
40
|
+
|
|
41
|
+
@tool
|
|
42
|
+
def setup_prisma(
|
|
43
|
+
project_dir: str,
|
|
44
|
+
regenerate: bool = True,
|
|
45
|
+
push_db: bool = True,
|
|
46
|
+
) -> Dict[str, Any]:
|
|
47
|
+
"""Set up or update Prisma client after schema changes.
|
|
48
|
+
|
|
49
|
+
This tool enforces the correct Prisma workflow:
|
|
50
|
+
1. Generates Prisma Client (TypeScript types)
|
|
51
|
+
2. Pushes schema to database
|
|
52
|
+
3. Verifies the singleton file exists
|
|
53
|
+
4. Returns the correct import paths to use
|
|
54
|
+
|
|
55
|
+
Call this tool:
|
|
56
|
+
- After creating or modifying prisma/schema.prisma
|
|
57
|
+
- When you see "Cannot find name 'Todo'" or similar type errors
|
|
58
|
+
- When you see "Module '@prisma/client' has no exported member" errors
|
|
59
|
+
|
|
60
|
+
Args:
|
|
61
|
+
project_dir: Path to the Next.js project directory
|
|
62
|
+
regenerate: Whether to run prisma generate (default: True)
|
|
63
|
+
push_db: Whether to run prisma db push (default: True)
|
|
64
|
+
|
|
65
|
+
Returns:
|
|
66
|
+
Dictionary with:
|
|
67
|
+
- success: bool
|
|
68
|
+
- generated: bool (whether prisma generate ran)
|
|
69
|
+
- pushed: bool (whether prisma db push ran)
|
|
70
|
+
- singleton_path: str (path to singleton file)
|
|
71
|
+
- import_patterns: dict (correct import statements to use)
|
|
72
|
+
- output: str (command output)
|
|
73
|
+
- error: str (if failed)
|
|
74
|
+
"""
|
|
75
|
+
try:
|
|
76
|
+
project_path = Path(project_dir).resolve()
|
|
77
|
+
if not project_path.exists():
|
|
78
|
+
return {
|
|
79
|
+
"success": False,
|
|
80
|
+
"error": f"Project directory does not exist: {project_dir}",
|
|
81
|
+
"error_type": "validation_error",
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
schema_path = project_path / "prisma" / "schema.prisma"
|
|
85
|
+
if not schema_path.exists():
|
|
86
|
+
return {
|
|
87
|
+
"success": False,
|
|
88
|
+
"error": f"Prisma schema not found at {schema_path}. Run 'npx prisma init' first.",
|
|
89
|
+
"error_type": "schema_error",
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
output_lines = []
|
|
93
|
+
generated = False
|
|
94
|
+
pushed = False
|
|
95
|
+
|
|
96
|
+
# Step 1: Generate Prisma Client
|
|
97
|
+
if regenerate:
|
|
98
|
+
logger.info(f"Running prisma generate in {project_dir}")
|
|
99
|
+
result = subprocess.run(
|
|
100
|
+
["npx", "prisma", "generate"],
|
|
101
|
+
cwd=str(project_path),
|
|
102
|
+
capture_output=True,
|
|
103
|
+
text=True,
|
|
104
|
+
timeout=120,
|
|
105
|
+
check=False,
|
|
106
|
+
)
|
|
107
|
+
output_lines.append("=== prisma generate ===")
|
|
108
|
+
output_lines.append(result.stdout)
|
|
109
|
+
if result.stderr:
|
|
110
|
+
output_lines.append(result.stderr)
|
|
111
|
+
|
|
112
|
+
if result.returncode != 0:
|
|
113
|
+
return {
|
|
114
|
+
"success": False,
|
|
115
|
+
"generated": False,
|
|
116
|
+
"error": f"prisma generate failed: {result.stderr}",
|
|
117
|
+
"error_type": "client_error",
|
|
118
|
+
"output": "\n".join(output_lines),
|
|
119
|
+
}
|
|
120
|
+
generated = True
|
|
121
|
+
|
|
122
|
+
# Step 2: Push schema to database
|
|
123
|
+
if push_db:
|
|
124
|
+
logger.info(f"Running prisma db push in {project_dir}")
|
|
125
|
+
result = subprocess.run(
|
|
126
|
+
["npx", "prisma", "db", "push"],
|
|
127
|
+
cwd=str(project_path),
|
|
128
|
+
capture_output=True,
|
|
129
|
+
text=True,
|
|
130
|
+
timeout=120,
|
|
131
|
+
check=False,
|
|
132
|
+
)
|
|
133
|
+
output_lines.append("\n=== prisma db push ===")
|
|
134
|
+
output_lines.append(result.stdout)
|
|
135
|
+
if result.stderr:
|
|
136
|
+
output_lines.append(result.stderr)
|
|
137
|
+
|
|
138
|
+
if result.returncode != 0:
|
|
139
|
+
return {
|
|
140
|
+
"success": False,
|
|
141
|
+
"generated": generated,
|
|
142
|
+
"pushed": False,
|
|
143
|
+
"error": f"prisma db push failed: {result.stderr}",
|
|
144
|
+
"error_type": "migration_error",
|
|
145
|
+
"output": "\n".join(output_lines),
|
|
146
|
+
}
|
|
147
|
+
pushed = True
|
|
148
|
+
|
|
149
|
+
# Step 3: Create singleton file if it doesn't exist
|
|
150
|
+
singleton_path = project_path / "src" / "lib" / "prisma.ts"
|
|
151
|
+
singleton_created = False
|
|
152
|
+
|
|
153
|
+
if not singleton_path.exists():
|
|
154
|
+
singleton_path.parent.mkdir(parents=True, exist_ok=True)
|
|
155
|
+
singleton_path.write_text(
|
|
156
|
+
PRISMA_SINGLETON_TEMPLATE, encoding="utf-8"
|
|
157
|
+
)
|
|
158
|
+
singleton_created = True
|
|
159
|
+
output_lines.append(
|
|
160
|
+
f"\nCreated Prisma singleton at {singleton_path}"
|
|
161
|
+
)
|
|
162
|
+
logger.info(f"Created Prisma singleton at {singleton_path}")
|
|
163
|
+
|
|
164
|
+
return {
|
|
165
|
+
"success": True,
|
|
166
|
+
"generated": generated,
|
|
167
|
+
"pushed": pushed,
|
|
168
|
+
"singleton_created": singleton_created,
|
|
169
|
+
"singleton_path": str(singleton_path.relative_to(project_path)),
|
|
170
|
+
"import_patterns": {
|
|
171
|
+
"client_instance": "import { prisma } from '@/lib/prisma'",
|
|
172
|
+
"model_types": "import { Todo, User } from '@prisma/client'",
|
|
173
|
+
"prisma_namespace": "import { Prisma } from '@prisma/client'",
|
|
174
|
+
},
|
|
175
|
+
"output": "\n".join(output_lines),
|
|
176
|
+
}
|
|
177
|
+
|
|
178
|
+
except subprocess.TimeoutExpired:
|
|
179
|
+
return {
|
|
180
|
+
"success": False,
|
|
181
|
+
"error": "Prisma command timed out (exceeded 120 seconds)",
|
|
182
|
+
"error_type": "runtime_error",
|
|
183
|
+
}
|
|
184
|
+
except Exception as e:
|
|
185
|
+
logger.error(f"Error in setup_prisma: {e}", exc_info=True)
|
|
186
|
+
return {
|
|
187
|
+
"success": False,
|
|
188
|
+
"error": str(e),
|
|
189
|
+
"error_type": "runtime_error",
|
|
190
|
+
}
|