Spaces:
Sleeping
Sleeping
Surface real error messages and fix LLM exception formatting
Browse files- LLM exceptions (401, rate limit, etc.) now show clean message instead
of raw HTML or full stack trace
- Backend error events now consistently use 'message' field
- Frontend reads event.message ?? event.error so actual errors are shown
- Bail early if LLM returns empty response
- backend/api/demo.py +12 -2
- frontend/src/components/ChatPanel.tsx +1 -1
backend/api/demo.py
CHANGED
|
@@ -170,10 +170,20 @@ async def execute_query_stream(req: ExecuteQueryRequest):
|
|
| 170 |
chunks.append(delta)
|
| 171 |
yield {"data": json.dumps({"type": "sql_chunk", "chunk": delta})}
|
| 172 |
except Exception as e:
|
| 173 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
| 174 |
break
|
| 175 |
|
| 176 |
generated_sql = _clean_sql("".join(chunks))
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 177 |
yield {"data": json.dumps({"type": "sql_complete", "sql": generated_sql})}
|
| 178 |
yield {"data": json.dumps({"type": "executing"})}
|
| 179 |
|
|
@@ -228,7 +238,7 @@ async def execute_query_stream(req: ExecuteQueryRequest):
|
|
| 228 |
except Exception:
|
| 229 |
pass
|
| 230 |
|
| 231 |
-
yield {"data": json.dumps({"type": "error", "
|
| 232 |
|
| 233 |
# Grader + RL update
|
| 234 |
grader_in = GraderInput(
|
|
|
|
| 170 |
chunks.append(delta)
|
| 171 |
yield {"data": json.dumps({"type": "sql_chunk", "chunk": delta})}
|
| 172 |
except Exception as e:
|
| 173 |
+
# Format LLM exception concisely (avoid dumping full HTML 401 pages)
|
| 174 |
+
err_str = str(e)
|
| 175 |
+
if len(err_str) > 300 or '<html' in err_str.lower():
|
| 176 |
+
err_str = f"LLM API error: {type(e).__name__} (check HF_TOKEN / model availability)"
|
| 177 |
+
yield {"data": json.dumps({"type": "error", "message": err_str, "error_class": "other"})}
|
| 178 |
break
|
| 179 |
|
| 180 |
generated_sql = _clean_sql("".join(chunks))
|
| 181 |
+
|
| 182 |
+
# If LLM returned nothing useful, bail early
|
| 183 |
+
if not generated_sql.strip():
|
| 184 |
+
yield {"data": json.dumps({"type": "error", "message": "LLM returned empty response", "error_class": "other"})}
|
| 185 |
+
break
|
| 186 |
+
|
| 187 |
yield {"data": json.dumps({"type": "sql_complete", "sql": generated_sql})}
|
| 188 |
yield {"data": json.dumps({"type": "executing"})}
|
| 189 |
|
|
|
|
| 238 |
except Exception:
|
| 239 |
pass
|
| 240 |
|
| 241 |
+
yield {"data": json.dumps({"type": "error", "message": error, "error_class": error_class_name})}
|
| 242 |
|
| 243 |
# Grader + RL update
|
| 244 |
grader_in = GraderInput(
|
frontend/src/components/ChatPanel.tsx
CHANGED
|
@@ -451,7 +451,7 @@ export function ChatPanel() {
|
|
| 451 |
} else if (event.type === 'error') {
|
| 452 |
updateMessage(msgId, {
|
| 453 |
status: 'error',
|
| 454 |
-
errorMsg: event.message as string,
|
| 455 |
})
|
| 456 |
} else if (event.type === 'gepa_start') {
|
| 457 |
setOptimizingBanner(true)
|
|
|
|
| 451 |
} else if (event.type === 'error') {
|
| 452 |
updateMessage(msgId, {
|
| 453 |
status: 'error',
|
| 454 |
+
errorMsg: ((event.message ?? event.error) as string | undefined) ?? 'Agent exhausted all repair attempts',
|
| 455 |
})
|
| 456 |
} else if (event.type === 'gepa_start') {
|
| 457 |
setOptimizingBanner(true)
|