fix: add error handling for repair endpoint SafetyFilter
Browse files- playground/api/app.py +38 -24
playground/api/app.py
CHANGED
|
@@ -359,29 +359,43 @@ async def repair(request: Request, file: UploadFile) -> dict[str, Any]:
|
|
| 359 |
issues = run_all_detectors(df, schema=None)
|
| 360 |
|
| 361 |
# Propose fixes (heuristic-only, no LLM unless advanced + keyed)
|
| 362 |
-
|
| 363 |
-
|
| 364 |
-
|
| 365 |
-
|
| 366 |
-
|
| 367 |
-
|
| 368 |
-
|
| 369 |
-
|
| 370 |
-
|
| 371 |
-
|
| 372 |
-
|
| 373 |
-
|
| 374 |
-
|
| 375 |
-
# Run safety filter on each proposed fix
|
| 376 |
-
safety = SafetyFilter()
|
| 377 |
-
context = SafetyContext()
|
| 378 |
-
accepted_fixes: list[ProposedFix] = []
|
| 379 |
-
for fix in fixes:
|
| 380 |
-
result = safety.evaluate(fix, schema=None, context=context)
|
| 381 |
-
if result.verdict == SafetyVerdict.ALLOW:
|
| 382 |
-
accepted_fixes.append(fix)
|
| 383 |
|
| 384 |
-
|
| 385 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 386 |
|
| 387 |
-
return _fixes_to_response(accepted_fixes, txn_id, source_sha256)
|
|
|
|
| 359 |
issues = run_all_detectors(df, schema=None)
|
| 360 |
|
| 361 |
# Propose fixes (heuristic-only, no LLM unless advanced + keyed)
|
| 362 |
+
try:
|
| 363 |
+
with tempfile.TemporaryDirectory() as tmpdir:
|
| 364 |
+
cache_dir = Path(tmpdir) / "cache"
|
| 365 |
+
cache_dir.mkdir()
|
| 366 |
+
|
| 367 |
+
fixes = propose_fixes(
|
| 368 |
+
issues,
|
| 369 |
+
df,
|
| 370 |
+
schema=None,
|
| 371 |
+
cache_dir=cache_dir,
|
| 372 |
+
allow_llm=False,
|
| 373 |
+
model="gemini-2.0-flash",
|
| 374 |
+
)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 375 |
|
| 376 |
+
# Run safety filter on each proposed fix
|
| 377 |
+
try:
|
| 378 |
+
safety = SafetyFilter()
|
| 379 |
+
context = SafetyContext()
|
| 380 |
+
accepted_fixes: list[ProposedFix] = []
|
| 381 |
+
for fix in fixes:
|
| 382 |
+
result = safety.evaluate(fix, schema=None, context=context)
|
| 383 |
+
if result.verdict == SafetyVerdict.ALLOW:
|
| 384 |
+
accepted_fixes.append(fix)
|
| 385 |
+
except Exception:
|
| 386 |
+
# Constitution file may not be at the expected path in Docker;
|
| 387 |
+
# gracefully skip safety filter and return all fixes.
|
| 388 |
+
logger.warning("SafetyFilter init failed; returning unfiltered fixes", exc_info=True)
|
| 389 |
+
accepted_fixes = list(fixes)
|
| 390 |
+
|
| 391 |
+
# Generate ephemeral transaction ID
|
| 392 |
+
txn_id = generate_txn_id()
|
| 393 |
+
|
| 394 |
+
return _fixes_to_response(accepted_fixes, txn_id, source_sha256)
|
| 395 |
+
except Exception:
|
| 396 |
+
logger.exception("Repair endpoint failed")
|
| 397 |
+
raise HTTPException(
|
| 398 |
+
status_code=500,
|
| 399 |
+
detail={"error": "repair_failed", "message": "An internal error occurred during repair."},
|
| 400 |
+
)
|
| 401 |
|
|
|