Skip to content

Commit 5e8866f

Browse files
authored
Merge pull request #13 from Acuspeedster/main
Fix: Bugs in the generate and compile and fix points
2 parents 69d0b8a + 96e1fe6 commit 5e8866f

File tree

4 files changed

+202
-122
lines changed

4 files changed

+202
-122
lines changed

.github/workflows/test-mcp-server.yml

Lines changed: 20 additions & 39 deletions
Original file line numberDiff line numberDiff line change
@@ -104,31 +104,15 @@ jobs:
104104
exit 1
105105
fi
106106
107-
# Check if response is JSON (starts with {) or text format
108-
if [[ "$RESPONSE" == {* ]]; then
109-
# JSON response (likely error)
110-
echo "Got JSON response (likely error):"
111-
echo "$RESPONSE" | jq || echo "$RESPONSE"
112-
113-
# Verify it's a valid response with attempts
114-
if echo "$RESPONSE" | jq -e '.attempts' > /dev/null; then
115-
echo "Compilation couldn't be fixed, but response format is valid"
116-
else
117-
echo "Invalid error response format"
118-
exit 1
119-
fi
120-
else
121-
# Text response (success case)
122-
# Verify the response format has filename markers
123-
if ! echo "$RESPONSE" | grep -q "\[filename:"; then
124-
echo "Response does not contain filename markers:"
125-
echo "$RESPONSE" | jq || echo "$RESPONSE"
126-
exit 1
127-
fi
128-
129-
echo "Compile and fix successful! Response contains code files in text format."
107+
# Check for success in response
108+
if ! echo "$RESPONSE" | jq -e '.success == true' > /dev/null; then
109+
echo "Compilation failed:"
130110
echo "$RESPONSE" | jq || echo "$RESPONSE"
111+
exit 1
131112
fi
113+
114+
echo "Compilation successful!"
115+
echo "$RESPONSE" | jq || echo "$RESPONSE"
132116
133117
- name: Test /generate endpoint
134118
run: |
@@ -248,22 +232,14 @@ jobs:
248232
# Save response to file for later use
249233
echo "$RESPONSE" > generate_output.txt
250234
251-
# Verify the response format has filename markers
252-
if ! echo "$RESPONSE" | grep -q "\[filename:"; then
253-
echo "Response does not contain filename markers:"
254-
echo "$RESPONSE" | head -20
235+
# Check for success in response
236+
if ! echo "$RESPONSE" | jq -e '.success == true' > /dev/null; then
237+
echo "Generation failed:"
255238
echo "status=error" >> $GITHUB_OUTPUT
239+
echo "$RESPONSE" | jq || echo "$RESPONSE"
256240
exit 1
257241
fi
258242
259-
# Check if this is a fallback template
260-
if echo "$RESPONSE" | grep -q "THIS IS A FALLBACK TEMPLATE - LLM generation failed"; then
261-
echo "WARNING: Response contains fallback template - LLM generation failed"
262-
echo "status=fallback" >> $GITHUB_OUTPUT
263-
# Exit with status 0 to allow workflow to continue, but we know it's a fallback
264-
exit 0
265-
fi
266-
267243
echo "Generate-sync successful! Response contains code files in text format."
268244
echo "status=success" >> $GITHUB_OUTPUT
269245
echo "$RESPONSE" | jq || echo "$RESPONSE"
@@ -278,13 +254,18 @@ jobs:
278254
fi
279255

280256
# Get the output from the previous step and remove the build status comment
281-
GENERATE_OUTPUT=$(cat generate_output.txt | sed '/^# Build/,$d')
282-
283-
# Pass the cleaned generated code directly to compile
257+
# GENERATE_OUTPUT=$(cat generate_output.txt | sed '/^# Build/,$d')
258+
# COMPILE_RESPONSE=$(curl -s -S -f -X POST http://localhost:8000/compile \
259+
# -H "Content-Type: application/json" \
260+
# -d "{
261+
# \"code\": $(python3 -c "import json, sys; print(json.dumps(sys.stdin.read()))" < <(echo "$GENERATE_OUTPUT"))
262+
# }" || echo "CURL_FAILED")
263+
264+
# Replace with:
284265
COMPILE_RESPONSE=$(curl -s -S -f -X POST http://localhost:8000/compile \
285266
-H "Content-Type: application/json" \
286267
-d "{
287-
\"code\": $(echo "$GENERATE_OUTPUT" | jq -Rs .)
268+
\"code\": $(python3 -c "import json, sys; print(json.dumps(sys.stdin.read()))" < <(echo "$GENERATE_OUTPUT"))
288269
}" || echo "CURL_FAILED")
289270

290271
if [ "$COMPILE_RESPONSE" = "CURL_FAILED" ]; then

.gitignore

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
.env
2+
qdrant_data

app/main.py

Lines changed: 73 additions & 56 deletions
Original file line numberDiff line numberDiff line change
@@ -38,18 +38,25 @@
3838
compiler = RustCompiler()
3939

4040
# Initialize vector store
41-
vector_store = QdrantStore(embedding_size=llm_embed_size)
42-
vector_store.create_collection("project_examples")
43-
vector_store.create_collection("error_examples")
44-
45-
# After initializing vector store
46-
from app.load_data import load_project_examples, load_error_examples
47-
48-
# Check if collections are empty and load data if needed
49-
if vector_store.count("project_examples") == 0:
50-
load_project_examples()
51-
if vector_store.count("error_examples") == 0:
52-
load_error_examples()
41+
try:
42+
vector_store = QdrantStore(embedding_size=llm_embed_size)
43+
if os.getenv("SKIP_VECTOR_SEARCH", "").lower() != "true":
44+
vector_store.create_collection("project_examples")
45+
vector_store.create_collection("error_examples")
46+
47+
# After initializing vector store
48+
from app.load_data import load_project_examples, load_error_examples
49+
50+
# Check if collections are empty and load data if needed
51+
if vector_store.count("project_examples") == 0:
52+
load_project_examples()
53+
if vector_store.count("error_examples") == 0:
54+
load_error_examples()
55+
except Exception as e:
56+
print(f"Warning: Vector store initialization failed: {e}")
57+
print("Continuing without vector store functionality...")
58+
# Create a dummy vector store
59+
vector_store = None
5360

5461
# Project generation request
5562
class ProjectRequest(BaseModel):
@@ -161,10 +168,6 @@ async def compile_and_fix_rust(request: dict):
161168

162169
# Pre-process code to fix common syntax errors
163170
code = request["code"]
164-
# Fix missing parenthesis in println! macro
165-
# if "println!(" in code and ");" not in code:
166-
# code = code.replace("println!(\"", "println!(\"")
167-
# code = code.replace("\" //", "\"); //")
168171

169172
# Create temp directory
170173
with tempfile.TemporaryDirectory() as temp_dir:
@@ -201,8 +204,17 @@ async def compile_and_fix_rust(request: dict):
201204
for filename, content in current_files.items():
202205
output_text += f"[filename: {filename}]\n{content}\n\n"
203206

204-
# For successful fixes, return a text response with the combined code
205-
return PlainTextResponse(content=output_text.strip())
207+
# Return JSON response instead of plain text
208+
return JSONResponse(content={
209+
"status": "success",
210+
"message": "Code fixed and compiled successfully",
211+
"attempts": attempts,
212+
"combined_text": output_text.strip(),
213+
"files": current_files,
214+
"build_output": output or "Build successful",
215+
"run_output": run_output if run_success else None,
216+
"build_success": True
217+
})
206218

207219
# If we've reached max attempts without success, stop
208220
if attempt == max_attempts - 1:
@@ -211,14 +223,15 @@ async def compile_and_fix_rust(request: dict):
211223
# Extract error context for LLM
212224
error_context = compiler.extract_error_context(output)
213225

214-
# Find similar errors in vector DB (commented out for now)
226+
# Find similar errors in vector DB
215227
similar_errors = []
216-
try:
217-
# Find similar errors in vector DB
218-
error_embedding = llm_client.get_embeddings([error_context["full_error"]])[0]
219-
similar_errors = vector_store.search("error_examples", error_embedding, limit=3)
220-
except Exception as e:
221-
print(f"Vector search error (non-critical): {e}")
228+
if vector_store is not None and os.getenv("SKIP_VECTOR_SEARCH", "").lower() != "true":
229+
try:
230+
# Find similar errors in vector DB
231+
error_embedding = llm_client.get_embeddings([error_context["full_error"]])[0]
232+
similar_errors = vector_store.search("error_examples", error_embedding, limit=3)
233+
except Exception as e:
234+
print(f"Vector search error (non-critical): {e}")
222235

223236
# Generate fix prompt
224237
fix_examples = ""
@@ -257,15 +270,26 @@ async def compile_and_fix_rust(request: dict):
257270
for filename, content in current_files.items():
258271
output_text += f"[filename: {filename}]\n{content}\n\n"
259272

273+
# Add explanation for build failure
274+
output_text += "\n# Build failed\n"
275+
output_text += f"\n# Note: The build failed after {max_attempts} fix attempts. Common reasons include:\n"
276+
output_text += "# - Complex syntax errors that are difficult to fix automatically\n"
277+
output_text += "# - Dependencies that cannot be resolved\n"
278+
output_text += "# - Logical errors in the code structure\n"
279+
if len(attempts) > 0:
280+
output_text += f"# The final error was: {attempts[-1]['output'].splitlines()[0] if attempts[-1]['output'] else 'Unknown error'}\n"
281+
260282
# If we've exhausted all attempts, return error
261283
return JSONResponse(content={
262-
"status": "error",
263-
"message": f"Failed to fix code: {attempts[-1]['output']}",
284+
"status": "failed",
285+
"message": f"Failed to fix code after {max_attempts} attempts",
264286
"attempts": attempts,
265287
"combined_text": output_text.strip(),
266-
"final_files": current_files
288+
"files": current_files,
289+
"build_output": attempts[-1]['output'] if attempts else "No compilation attempts were made",
290+
"build_success": False
267291
})
268-
292+
269293
async def handle_project_generation(
270294
project_id: str,
271295
project_dir: str,
@@ -391,7 +415,7 @@ async def handle_project_generation(
391415
fix_examples = "Here are some examples of similar errors and their fixes:\n\n"
392416
for i, err in enumerate(similar_errors):
393417
fix_examples += f"Example {i+1}:\n{err['error']}\nFix: {err['solution']}\n\n"
394-
418+
395419
fix_prompt = f"""
396420
Here is a Rust project that failed to compile. Help me fix the compilation errors.
397421
@@ -592,7 +616,6 @@ async def generate_project_sync(request: ProjectRequest):
592616
})
593617

594618
# DON'T save status here - remove this line
595-
# save_status(temp_dir, status)
596619

597620
# Extract error context
598621
error_context = compiler.extract_error_context(output)
@@ -654,32 +677,26 @@ async def generate_project_sync(request: ProjectRequest):
654677
except Exception as e:
655678
print(f"Error reading file {f}: {e}")
656679

657-
if success:
658-
# Project compiled successfully
659-
status.update({
660-
"status": "completed",
661-
"message": "Project generated successfully",
662-
"build_output": output
663-
})
664-
665-
# Add build status
666-
all_files_content += "\n# Build succeeded\n"
667-
else:
668-
# Build failed
669-
status.update({
670-
"status": "failed",
671-
"message": "Failed to generate working project",
672-
"build_output": output
673-
})
674-
675-
# Add build status
676-
all_files_content += "\n# Build failed\n"
677-
678-
# DON'T save status here - remove this line
679-
# save_status(temp_dir, status)
680+
# Add build status to the combined text
681+
all_files_content += "\n# Build " + ("succeeded" if success else "failed") + "\n"
680682

681-
# Return the response while still inside the with block
682-
return PlainTextResponse(content=all_files_content)
683+
# Add explanation when build fails
684+
if not success:
685+
all_files_content += f"\n# Note: The build failed because of errors in the generated code. Common reasons include:\n"
686+
all_files_content += "# - Incorrect or non-existent crate versions specified in Cargo.toml\n"
687+
all_files_content += "# - Improper API usage in the generated code\n"
688+
all_files_content += "# - Missing or incompatible dependencies\n"
689+
all_files_content += f"# The specific error was: {output.splitlines()[0] if output else 'Unknown error'}\n"
690+
691+
# Return JSON response instead of plain text
692+
return JSONResponse(content={
693+
"status": "success" if success else "failed",
694+
"message": "Project generated successfully" if success else "Failed to generate working project",
695+
"combined_text": all_files_content.strip(),
696+
"files": {f: open(os.path.join(temp_dir, f), 'r').read() for f in file_paths if os.path.exists(os.path.join(temp_dir, f))},
697+
"build_output": output,
698+
"build_success": success
699+
})
683700

684701
except Exception as e:
685702
raise HTTPException(status_code=500, detail=f"Error generating project: {str(e)}")

0 commit comments

Comments
 (0)