| 497 | } |
| 498 | |
| 499 | func parseAnalysisResponse(response string) analysisResult { |
| 500 | // Strip markdown code blocks if present |
| 501 | cleaned := response |
| 502 | cleaned = strings.TrimSpace(cleaned) |
| 503 | if strings.HasPrefix(cleaned, "```json") { |
| 504 | cleaned = strings.TrimPrefix(cleaned, "```json") |
| 505 | if idx := strings.LastIndex(cleaned, "```"); idx >= 0 { |
| 506 | cleaned = cleaned[:idx] |
| 507 | } |
| 508 | } else if strings.HasPrefix(cleaned, "```") { |
| 509 | cleaned = strings.TrimPrefix(cleaned, "```") |
| 510 | if idx := strings.LastIndex(cleaned, "```"); idx >= 0 { |
| 511 | cleaned = cleaned[:idx] |
| 512 | } |
| 513 | } |
| 514 | cleaned = strings.TrimSpace(cleaned) |
| 515 | |
| 516 | var result analysisResult |
| 517 | if err := json.Unmarshal([]byte(cleaned), &result); err != nil { |
| 518 | // Fallback: treat entire response as analysis text |
| 519 | return analysisResult{ |
| 520 | Analysis: response, |
| 521 | Confidence: 0.5, |
| 522 | Recommendations: []string{i18n.T("server.analysis.parse_fallback")}, |
| 523 | } |
| 524 | } |
| 525 | |
| 526 | // Clamp confidence |
| 527 | if result.Confidence < 0 { |
| 528 | result.Confidence = 0 |
| 529 | } |
| 530 | if result.Confidence > 1 { |
| 531 | result.Confidence = 1 |
| 532 | } |
| 533 | |
| 534 | return result |
| 535 | } |
| 536 | |
| 537 | // --- Agentic Remediation --- |
| 538 | |