diff --git a/server/debug_handlers.go b/server/debug_handlers.go index 00dceea25f620bc0b273804fd281af5548d387b6..e8a7d464a85aa093a54966779ca0644a2e10ed41 100644 --- a/server/debug_handlers.go +++ b/server/debug_handlers.go @@ -90,6 +90,36 @@ func (s *Server) handleDebugLLMResponseBody(w http.ResponseWriter, r *http.Reque w.Write([]byte(*body)) } +// handleDebugLLMRequestBodyFull returns the full reconstructed request body, +// including prefix data from the prefix chain. +func (s *Server) handleDebugLLMRequestBodyFull(w http.ResponseWriter, r *http.Request) { + ctx := r.Context() + + idStr := r.PathValue("id") + id, err := strconv.ParseInt(idStr, 10, 64) + if err != nil { + http.Error(w, "Invalid ID", http.StatusBadRequest) + return + } + + // Use the existing DB method to reconstruct the full body + fullBody, err := s.db.GetFullLLMRequestBody(ctx, id) + if err != nil { + s.logger.Error("Failed to get full LLM request body", "error", err, "id", id) + http.Error(w, "Not found", http.StatusNotFound) + return + } + + if fullBody == "" { + w.Header().Set("Content-Type", "application/json") + w.Write([]byte("null")) + return + } + + w.Header().Set("Content-Type", "application/json") + w.Write([]byte(fullBody)) +} + const debugLLMRequestsHTML = `
@@ -102,10 +132,10 @@ body { font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif; margin: 0; padding: 20px; - background: #1a1a1a; - color: #e0e0e0; + background: #fff; + color: #1a1a1a; } -h1 { margin: 0 0 20px 0; font-size: 24px; color: #fff; } +h1 { margin: 0 0 20px 0; font-size: 24px; color: #000; } table { width: 100%; border-collapse: collapse; @@ -114,38 +144,40 @@ table { th, td { padding: 8px 12px; text-align: left; - border-bottom: 1px solid #333; + border-bottom: 1px solid #e0e0e0; } th { - background: #252525; + background: #f5f5f5; font-weight: 600; position: sticky; top: 0; } -tr:hover { background: #252525; } +tr:hover { background: #f8f8f8; } .mono { font-family: 'SF Mono', Monaco, monospace; font-size: 12px; } -.error { color: #ff6b6b; } -.success { color: #69db7c; } +.error { color: #d32f2f; } +.success { color: #2e7d32; } .btn { - background: #333; - border: 1px solid #444; - color: #e0e0e0; + background: #f5f5f5; + border: 1px solid #ccc; + color: #333; padding: 4px 8px; border-radius: 4px; cursor: pointer; font-size: 12px; } -.btn:hover { background: #444; } +.btn:hover { background: #e8e8e8; } .btn:disabled { opacity: 0.5; cursor: not-allowed; } +.btn.active { background: #1976d2; color: #fff; border-color: #1565c0; } .json-viewer { - background: #1e1e1e; - border: 1px solid #333; + background: #fafafa; + border: 1px solid #e0e0e0; border-radius: 4px; padding: 12px; - margin-top: 8px; overflow-x: auto; - max-height: 400px; + max-height: 600px; overflow-y: auto; + flex: 1; + min-width: 0; } .json-viewer pre { margin: 0; @@ -155,35 +187,42 @@ tr:hover { background: #252525; } word-wrap: break-word; } .collapsed { display: none; } -.size { color: #888; font-size: 11px; } -.prefix { color: #ffd43b; } -.dedup-info { color: #74c0fc; font-size: 11px; } -.loading { color: #888; font-style: italic; } -.expand-row { background: #1e1e1e; } +.size { color: #666; font-size: 11px; } +.prefix { color: #f57c00; } +.dedup-info { color: #1976d2; font-size: 11px; } +.loading { color: #666; font-style: italic; } +.expand-row { background: #fafafa; } .expand-row td { padding: 0; } .expand-content { padding: 12px; } -.expand-tabs { +.panels { display: flex; - gap: 8px; - margin-bottom: 12px; + gap: 16px; } -.tab-btn { - background: transparent; - border: 1px solid #444; - color: #888; - padding: 6px 12px; - border-radius: 4px; - cursor: pointer; +.panel { + flex: 1; + min-width: 0; + display: flex; + flex-direction: column; } -.tab-btn.active { - background: #333; - color: #fff; - border-color: #555; +.panel-header { + font-weight: 600; + margin-bottom: 8px; + color: #333; + display: flex; + align-items: center; + gap: 8px; } -.tab-content { display: none; } -.tab-content.active { display: block; } -.model-display { color: #a5d6ff; } -.model-id { color: #888; font-size: 11px; } +.panel-header .btn { + font-size: 11px; + padding: 2px 6px; +} +.model-display { color: #1976d2; } +.model-id { color: #666; font-size: 11px; } +.string { color: #2e7d32; } +.number { color: #e65100; } +.boolean { color: #0097a7; } +.null { color: #7b1fa2; } +.key { color: #c62828; } @@ -298,13 +337,13 @@ function renderTable(requests) {