package cli import ( "fmt" "strconv" "strings" "time" tea "github.com/charmbracelet/bubbletea" "gitea.mynodes.xyz/ilker/llmgw/internal/store" ) // The audit view: who changed what, newest first — the same as `llmgw ctl // audit`. func (m consoleModel) auditPanel(pw int) (string, string, string) { keys := "→ or Enter open · ↑↓ choose · Q leave" if m.inPanel { keys = "↑↓ row · Enter what it was given · ← back · Q leave" } head := "\n " + sDim.Render("Every change through ctl, this console and the /admin pages, the last week.") + "\n\n" var rows [][]string for _, e := range m.data.audit { status := strconv.Itoa(e.Status) if e.Status >= 400 { status = sBad.Render(status) } rows = append(rows, []string{ageShort(e.At), e.Actor, e.Source, e.Action, dash(e.Target), status}) } if len(rows) == 0 { return "Audit", head + " " + sDim.Render("Nothing changed in the last week, or this control plane has no store."), keys } return "Audit", head + table([]string{"WHEN", "WHO", "VIA", "WHAT", "TARGET", "STATUS"}, rows, m.row, pw, m.inPanel), keys } // auditDialog is one change in full. func auditDialog(e store.AuditEvent) (string, string) { var b strings.Builder fmt.Fprintf(&b, "%s, by %s through %s\nstatus %d\n", e.At.Format(time.DateTime), e.Actor, e.Source, e.Status) if e.Target != "" { fmt.Fprintf(&b, "target %s\n", e.Target) } if e.Detail != "" && e.Detail != "{}" { fmt.Fprintf(&b, "\n%s\n", wrap(e.Detail, 80, "")) } b.WriteString("\n" + sDim.Render("any key")) return e.Action, b.String() } // usageExportForm writes usage to a CSV file on this machine, as `llmgw ctl // usage export` does. func (m *consoleModel) usageExportForm() { now := time.Now().UTC() first := time.Date(now.Year(), now.Month(), 1, 0, 0, 0, 0, time.UTC) m.openForm(&formDialog{title: "Export usage as CSV", fields: []formField{ textF("from", first.AddDate(0, -1, 0).Format("2006-01-02"), "first day"), textF("to", first.Format("2006-01-02"), "the day after the last"), textF("period", "day", "hour, day or month"), textF("by", "project,model", "org, team, project, user, key, model"), textF("file", "/tmp/llmgw-usage-"+first.AddDate(0, -1, 0).Format("2006-01")+".csv", "written on this machine"), }, submit: func(m *consoleModel, v []string) (tea.Cmd, error) { if v[4] == "" { return nil, fmt.Errorf("a file to write") } return m.runCLI("Export usage", "ctl", "usage", "export", "--from", v[0], "--to", v[1], "--period", v[2], "--by", v[3], "--output", v[4]), nil }}) }