Spaces:
Running
Running
Upload folder using huggingface_hub
Browse files- src/api/models.py +1 -0
- src/api/routers/triage.py +1 -0
- src/api/ui.py +38 -1
- src/db/repository.py +1 -1
src/api/models.py
CHANGED
|
@@ -269,6 +269,7 @@ class TriageResultResponse(BaseModel):
|
|
| 269 |
created_at: datetime = Field(default_factory=datetime.utcnow)
|
| 270 |
completed_at: datetime | None = None
|
| 271 |
processing_ms: int | None = Field(None, description="Total triage latency in milliseconds.")
|
|
|
|
| 272 |
|
| 273 |
|
| 274 |
class HealthResponse(BaseModel):
|
|
|
|
| 269 |
created_at: datetime = Field(default_factory=datetime.utcnow)
|
| 270 |
completed_at: datetime | None = None
|
| 271 |
processing_ms: int | None = Field(None, description="Total triage latency in milliseconds.")
|
| 272 |
+
error_message: str | None = Field(None, description="Detailed error message if processing failed.")
|
| 273 |
|
| 274 |
|
| 275 |
class HealthResponse(BaseModel):
|
src/api/routers/triage.py
CHANGED
|
@@ -123,6 +123,7 @@ def row_to_response(row: dict[str, Any], violations: list[dict] | None = None) -
|
|
| 123 |
created_at=created_at or datetime.utcnow(),
|
| 124 |
completed_at=completed_at,
|
| 125 |
processing_ms=processing_ms,
|
|
|
|
| 126 |
)
|
| 127 |
|
| 128 |
|
|
|
|
| 123 |
created_at=created_at or datetime.utcnow(),
|
| 124 |
completed_at=completed_at,
|
| 125 |
processing_ms=processing_ms,
|
| 126 |
+
error_message=row.get("error_message"),
|
| 127 |
)
|
| 128 |
|
| 129 |
|
src/api/ui.py
CHANGED
|
@@ -1215,8 +1215,16 @@ HTML_CONTENT = """<!DOCTYPE html>
|
|
| 1215 |
|
| 1216 |
const data = await response.json();
|
| 1217 |
|
| 1218 |
-
if(data.status
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1219 |
clearInterval(pollInterval);
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1220 |
displayTriageResults(data);
|
| 1221 |
btn.disabled = false;
|
| 1222 |
btn.innerText = "Dispatch to Triage Pipeline";
|
|
@@ -1234,6 +1242,35 @@ HTML_CONTENT = """<!DOCTYPE html>
|
|
| 1234 |
|
| 1235 |
// Display results in dashboard metrics cards
|
| 1236 |
function displayTriageResults(data) {
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1237 |
// Priority
|
| 1238 |
const priorityVal = data.priority || "Low";
|
| 1239 |
const priorityEl = document.getElementById('metric-priority');
|
|
|
|
| 1215 |
|
| 1216 |
const data = await response.json();
|
| 1217 |
|
| 1218 |
+
if (data.status === "processing") {
|
| 1219 |
+
document.getElementById('metric-resolution').innerText = `Triage active: Supervisor routing & agent network running (attempt ${attempts}/15)...`;
|
| 1220 |
+
}
|
| 1221 |
+
|
| 1222 |
+
if(data.status !== "pending" && data.status !== "processing" || attempts >= maxAttempts) {
|
| 1223 |
clearInterval(pollInterval);
|
| 1224 |
+
if (attempts >= maxAttempts && (data.status === "pending" || data.status === "processing")) {
|
| 1225 |
+
data.status = "failed";
|
| 1226 |
+
data.error_message = "Triage pipeline execution timed out after 15 seconds. The supervisor did not complete in time.";
|
| 1227 |
+
}
|
| 1228 |
displayTriageResults(data);
|
| 1229 |
btn.disabled = false;
|
| 1230 |
btn.innerText = "Dispatch to Triage Pipeline";
|
|
|
|
| 1242 |
|
| 1243 |
// Display results in dashboard metrics cards
|
| 1244 |
function displayTriageResults(data) {
|
| 1245 |
+
if (data.status === "failed") {
|
| 1246 |
+
const priorityEl = document.getElementById('metric-priority');
|
| 1247 |
+
priorityEl.innerText = "FAILED";
|
| 1248 |
+
priorityEl.className = "metric-value priority-badge priority-critical";
|
| 1249 |
+
|
| 1250 |
+
document.getElementById('metric-routing').innerText = "Aborted";
|
| 1251 |
+
document.getElementById('metric-outage').innerText = "Error";
|
| 1252 |
+
document.getElementById('metric-churn').innerText = "N/A";
|
| 1253 |
+
document.getElementById('churn-progress').style.width = "0%";
|
| 1254 |
+
|
| 1255 |
+
const resolutionEl = document.getElementById('metric-resolution');
|
| 1256 |
+
resolutionEl.innerHTML = `
|
| 1257 |
+
<div style="color: var(--danger); font-weight: 700; font-size: 15px; margin-bottom: 8px;">Triage Pipeline Execution Failed ❌</div>
|
| 1258 |
+
<div style="font-family: monospace; background: rgba(239, 68, 68, 0.08); border: 1px solid rgba(239, 68, 68, 0.2); padding: 12px; border-radius: 8px; color: #fca5a5; font-size: 12.5px; margin-bottom: 12px; overflow-x: auto; white-space: pre-wrap; line-height: 1.4;">${data.error_message || 'An unexpected exception occurred.'}</div>
|
| 1259 |
+
<div style="font-size: 12px; color: var(--text-muted);">
|
| 1260 |
+
<strong>Next Steps:</strong> Check system logs, verify Supabase credentials/IP reachability, and check the status of external LLM endpoints (e.g. OpenRouter key balance).
|
| 1261 |
+
</div>
|
| 1262 |
+
`;
|
| 1263 |
+
|
| 1264 |
+
document.getElementById('metric-pii-log').innerText = `[Pipeline Aborted]\n- Ticket ID: ${data.ticket_id || '--'}\n- Status: Failed\n- Error: ${data.error_message || 'unknown'}`;
|
| 1265 |
+
|
| 1266 |
+
const safetyEl = document.getElementById('safety-indicator');
|
| 1267 |
+
const safetyText = document.getElementById('safety-text');
|
| 1268 |
+
safetyEl.className = "safety-banner safety-blocked";
|
| 1269 |
+
safetyText.innerText = "🛡️ AI Compliance Check: Aborted due to system error.";
|
| 1270 |
+
safetyEl.style.display = "flex";
|
| 1271 |
+
return;
|
| 1272 |
+
}
|
| 1273 |
+
|
| 1274 |
// Priority
|
| 1275 |
const priorityVal = data.priority || "Low";
|
| 1276 |
const priorityEl = document.getElementById('metric-priority');
|
src/db/repository.py
CHANGED
|
@@ -401,7 +401,7 @@ class TicketRepository:
|
|
| 401 |
try:
|
| 402 |
query = (
|
| 403 |
sb.table("tickets")
|
| 404 |
-
.select("
|
| 405 |
.eq("tenant_id", self.tenant_id)
|
| 406 |
.order("created_at", desc=True)
|
| 407 |
.limit(limit)
|
|
|
|
| 401 |
try:
|
| 402 |
query = (
|
| 403 |
sb.table("tickets")
|
| 404 |
+
.select("*")
|
| 405 |
.eq("tenant_id", self.tenant_id)
|
| 406 |
.order("created_at", desc=True)
|
| 407 |
.limit(limit)
|