Spaces:
Sleeping
Sleeping
Commit Β·
4771f50
1
Parent(s): 7c2e633
feat: Complete API response corrections - add pipelines endpoint and enhanced error handling
Browse files- Added GET /api/v2/sessions/{session_id}/pipelines endpoint
- Returns all pipeline executions with full component details
- Includes component_id, status, output, errors, metadata
- Removes internal S3 keys from response
- Enhanced pipeline completion responses
- Added output_id and download_url to final_output
- Enables direct download of pipeline results
- Improved error handling
- Added component-level error details in error responses
- Includes failed_component with component_id, tool_name, and error
- Better debugging and UI error display
All API corrections from specification now fully implemented.
- api_routes_v2.py +89 -2
api_routes_v2.py
CHANGED
|
@@ -963,6 +963,55 @@ async def delete_session(session_id: str):
|
|
| 963 |
|
| 964 |
return {"status": "deleted", "session_id": session_id}
|
| 965 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 966 |
# ========================
|
| 967 |
# UNIFIED CHAT (non-streaming)
|
| 968 |
# ========================
|
|
@@ -1151,7 +1200,18 @@ async def chat_unified(
|
|
| 1151 |
result_text = _extract_user_facing_text(result)
|
| 1152 |
friendly = f"π Pipeline completed successfully!"
|
| 1153 |
output = {"component_summary": "Pipeline executed successfully", "steps": len(proposed.get("pipeline_steps", proposed.get("components", [])))}
|
| 1154 |
-
final_output = {"text": result_text
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1155 |
|
| 1156 |
api_data = {
|
| 1157 |
"type": "pipeline_completed",
|
|
@@ -1172,8 +1232,35 @@ async def chat_unified(
|
|
| 1172 |
pipeline_id = proposed.get("pipeline_id")
|
| 1173 |
if pipeline_id:
|
| 1174 |
_update_pipeline_status(pipeline_id, chat_id, "failed", result={"error": str(e)})
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1175 |
friendly = f"β Pipeline execution failed: {str(e)}"
|
| 1176 |
-
api_data = {
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1177 |
return _assistant_response_payload(
|
| 1178 |
chat_id=chat_id,
|
| 1179 |
friendly_response=friendly,
|
|
|
|
| 963 |
|
| 964 |
return {"status": "deleted", "session_id": session_id}
|
| 965 |
|
| 966 |
+
@router.get("/sessions/{session_id}/pipelines", response_model=Dict[str, Any])
|
| 967 |
+
async def get_session_pipelines(session_id: str):
|
| 968 |
+
"""
|
| 969 |
+
Get all pipeline executions for a session with full component details
|
| 970 |
+
"""
|
| 971 |
+
try:
|
| 972 |
+
from services.pipeline_manager import get_pipeline_manager
|
| 973 |
+
pipeline_mgr = get_pipeline_manager()
|
| 974 |
+
|
| 975 |
+
# Get all pipelines for this session from pipeline_manager
|
| 976 |
+
pipelines = pipeline_mgr.get_session_pipelines(session_id, limit=100)
|
| 977 |
+
|
| 978 |
+
# Process each pipeline to add component details and remove internal fields
|
| 979 |
+
enhanced_pipelines = []
|
| 980 |
+
for pipeline in pipelines:
|
| 981 |
+
enhanced_pipe = pipeline.copy()
|
| 982 |
+
|
| 983 |
+
# Rename result_preview to result if present
|
| 984 |
+
if "result_preview" in enhanced_pipe:
|
| 985 |
+
enhanced_pipe["result"] = enhanced_pipe.pop("result_preview")
|
| 986 |
+
|
| 987 |
+
# Remove internal S3 keys
|
| 988 |
+
enhanced_pipe.pop("pipeline_s3_key", None)
|
| 989 |
+
enhanced_pipe.pop("pipeline_definition_s3_key", None)
|
| 990 |
+
|
| 991 |
+
# Add hasError if not present
|
| 992 |
+
if "hasError" not in enhanced_pipe:
|
| 993 |
+
enhanced_pipe["hasError"] = enhanced_pipe.get("status") == "failed"
|
| 994 |
+
|
| 995 |
+
# Ensure final_output_url is included (presigned URL)
|
| 996 |
+
if "final_output_presigned_url" in enhanced_pipe:
|
| 997 |
+
enhanced_pipe["final_output_url"] = enhanced_pipe["final_output_presigned_url"]
|
| 998 |
+
|
| 999 |
+
# Components are already in the correct format from pipeline_manager
|
| 1000 |
+
# They include: component_id, status, component_output, hasError, error, metadata
|
| 1001 |
+
|
| 1002 |
+
enhanced_pipelines.append(enhanced_pipe)
|
| 1003 |
+
|
| 1004 |
+
return {
|
| 1005 |
+
"session_id": session_id,
|
| 1006 |
+
"pipelines": enhanced_pipelines
|
| 1007 |
+
}
|
| 1008 |
+
|
| 1009 |
+
except Exception as e:
|
| 1010 |
+
raise HTTPException(
|
| 1011 |
+
status_code=500,
|
| 1012 |
+
detail=f"Error retrieving pipelines: {str(e)}"
|
| 1013 |
+
)
|
| 1014 |
+
|
| 1015 |
# ========================
|
| 1016 |
# UNIFIED CHAT (non-streaming)
|
| 1017 |
# ========================
|
|
|
|
| 1200 |
result_text = _extract_user_facing_text(result)
|
| 1201 |
friendly = f"π Pipeline completed successfully!"
|
| 1202 |
output = {"component_summary": "Pipeline executed successfully", "steps": len(proposed.get("pipeline_steps", proposed.get("components", [])))}
|
| 1203 |
+
final_output = {"text": result_text}
|
| 1204 |
+
# Add output_id and download_url from pipeline_manager
|
| 1205 |
+
if pipeline_id:
|
| 1206 |
+
try:
|
| 1207 |
+
from services.pipeline_manager import get_pipeline_manager
|
| 1208 |
+
pipeline_mgr = get_pipeline_manager()
|
| 1209 |
+
pipeline_record = pipeline_mgr.get_pipeline(pipeline_id)
|
| 1210 |
+
if pipeline_record:
|
| 1211 |
+
final_output["output_id"] = pipeline_record.get("output_id")
|
| 1212 |
+
final_output["download_url"] = pipeline_record.get("final_output_presigned_url")
|
| 1213 |
+
except Exception as e:
|
| 1214 |
+
print(f"Warning: Could not get output_id/download_url: {e}")
|
| 1215 |
|
| 1216 |
api_data = {
|
| 1217 |
"type": "pipeline_completed",
|
|
|
|
| 1232 |
pipeline_id = proposed.get("pipeline_id")
|
| 1233 |
if pipeline_id:
|
| 1234 |
_update_pipeline_status(pipeline_id, chat_id, "failed", result={"error": str(e)})
|
| 1235 |
+
|
| 1236 |
+
# Get component-level error details
|
| 1237 |
+
failed_component = None
|
| 1238 |
+
if pipeline_id:
|
| 1239 |
+
try:
|
| 1240 |
+
from services.pipeline_manager import get_pipeline_manager
|
| 1241 |
+
pipeline_mgr = get_pipeline_manager()
|
| 1242 |
+
pipeline_record = pipeline_mgr.get_pipeline(pipeline_id)
|
| 1243 |
+
if pipeline_record and pipeline_record.get("components"):
|
| 1244 |
+
# Find first failed component
|
| 1245 |
+
for comp in pipeline_record.get("components", []):
|
| 1246 |
+
if comp.get("hasError") or comp.get("status") == "failed":
|
| 1247 |
+
failed_component = {
|
| 1248 |
+
"component_id": comp.get("component_id"),
|
| 1249 |
+
"tool_name": comp.get("component_name"),
|
| 1250 |
+
"error": comp.get("error")
|
| 1251 |
+
}
|
| 1252 |
+
break
|
| 1253 |
+
except Exception as comp_error:
|
| 1254 |
+
print(f"Warning: Could not get component error details: {comp_error}")
|
| 1255 |
+
|
| 1256 |
friendly = f"β Pipeline execution failed: {str(e)}"
|
| 1257 |
+
api_data = {
|
| 1258 |
+
"type": "error",
|
| 1259 |
+
"error_code": "PIPELINE_EXECUTION_FAILED",
|
| 1260 |
+
"message": str(e)
|
| 1261 |
+
}
|
| 1262 |
+
if failed_component:
|
| 1263 |
+
api_data["failed_component"] = failed_component
|
| 1264 |
return _assistant_response_payload(
|
| 1265 |
chat_id=chat_id,
|
| 1266 |
friendly_response=friendly,
|