package api import ( "encoding/json" "net/http" "path/filepath" "strconv" "time" "github.com/will/k8s-agent-dashboard/internal/claude" ) type BacklogResponse struct { Limit int `json:"limit"` Events []claude.Event `json:"events"` } func GetClaudeLiveBacklog(loader ClaudeLoader) http.HandlerFunc { return func(w http.ResponseWriter, r *http.Request) { limit := 200 if l := r.URL.Query().Get("limit"); l != "" { if n, err := strconv.Atoi(l); err == nil && n > 0 { limit = n if limit > 1000 { limit = 1000 } } } historyPath := filepath.Join(loader.ClaudeDir(), "history.jsonl") lines, err := claude.TailLastNLines(historyPath, limit) if err != nil { respondError(w, http.StatusInternalServerError, err.Error()) return } events := make([]claude.Event, 0, len(lines)) for _, line := range lines { ev := parseHistoryLine(line) events = append(events, ev) } respondJSON(w, http.StatusOK, BacklogResponse{ Limit: limit, Events: events, }) } } func parseHistoryLine(line string) claude.Event { data := map[string]any{ "rawLine": line, } var jsonData map[string]any if err := json.Unmarshal([]byte(line), &jsonData); err != nil { data["parseError"] = err.Error() } else { data["json"] = jsonData summary := map[string]string{} if v, ok := jsonData["sessionId"].(string); ok { summary["sessionId"] = v } if v, ok := jsonData["project"].(string); ok { summary["project"] = v } if v, ok := jsonData["display"].(string); ok { summary["display"] = v } data["summary"] = summary } return claude.Event{ TS: time.Now(), Type: claude.EventTypeHistoryAppend, Data: data, } }