feat: delete traffic targets and LLM task conversations from UI
Add delete controls to the Traffic and LLM Records pages so users can purge recorded data without hand-editing the data volume. Traffic page: - Host target picker (Popover with checkboxes + select-all toggle) - Exact-match batch delete for multiple hosts (DELETE /api/traffic/hosts) - Substring delete for the host-filter input (DELETE /api/traffic?host=) - Orphaned content-addressed blob garbage collection after deletes - Distinct-hosts endpoint (GET /api/traffic/hosts) for the picker LLM Records page: - Task picker dropdown (distinct task_id + record counts) - Per-task delete (DELETE /api/llm/records?task=) Other: - Add /dist/ to .gitignore (build artifact) - Extend traffic_test.go with DeleteHost, DeleteHostsExact, Hosts tests - Fix Popover render bug (replace ScrollArea that broke height calc) - Remove fade/zoom animation on the host picker Popover
This commit is contained in:
1 parent
5962826f2d
commit
c76d0f4c93
12 files changed
+883
-20
No files matched your search
+30
-1
@@ -3,6 +3,7 @@ package server
|
||||
import (
|
||||
"net/http"
|
||||
"strconv"
|
||||
"strings"
|
||||
)
|
||||
|
||||
// pgListCommands returns tool executions (any tool) from the activity table.
|
||||
@@ -34,8 +35,9 @@ func (s *Server) pgListLLMRecords(w http.ResponseWriter, r *http.Request) {
|
||||
size := atoiDefault(q.Get("size"), 50)
|
||||
model := q.Get("model")
|
||||
session := q.Get("session")
|
||||
task := q.Get("task")
|
||||
|
||||
records, total, err := s.m.PG().ListLLMRecords(model, session, page, size)
|
||||
records, total, err := s.m.PG().ListLLMRecords(model, session, task, page, size)
|
||||
if err != nil {
|
||||
writeErr(w, 500, err.Error())
|
||||
return
|
||||
@@ -43,6 +45,33 @@ func (s *Server) pgListLLMRecords(w http.ResponseWriter, r *http.Request) {
|
||||
writeJSON(w, 200, map[string]any{"records": records, "total": total})
|
||||
}
|
||||
|
||||
// pgLLMTasks returns distinct recorded tasks with counts, for the page's task
|
||||
// picker (pick a task → filter the list, then delete its conversations).
|
||||
func (s *Server) pgLLMTasks(w http.ResponseWriter, r *http.Request) {
|
||||
tasks, err := s.m.PG().LLMTasks()
|
||||
if err != nil {
|
||||
writeErr(w, 500, err.Error())
|
||||
return
|
||||
}
|
||||
writeJSON(w, 200, map[string]any{"tasks": tasks})
|
||||
}
|
||||
|
||||
// pgDeleteLLMRecords removes all LLM records for one exact task_id (the same
|
||||
// match the task picker uses). Empty task → 400. Returns rows deleted.
|
||||
func (s *Server) pgDeleteLLMRecords(w http.ResponseWriter, r *http.Request) {
|
||||
task := strings.TrimSpace(r.URL.Query().Get("task"))
|
||||
if task == "" {
|
||||
writeErr(w, 400, "missing task")
|
||||
return
|
||||
}
|
||||
n, err := s.m.PG().DeleteLLMRecords(task)
|
||||
if err != nil {
|
||||
writeErr(w, 500, err.Error())
|
||||
return
|
||||
}
|
||||
writeJSON(w, 200, map[string]any{"deleted": n})
|
||||
}
|
||||
|
||||
// pgGetLLMRecord returns a single LLM record with full request/response bodies.
|
||||
func (s *Server) pgGetLLMRecord(w http.ResponseWriter, r *http.Request) {
|
||||
id, err := strconv.ParseInt(r.PathValue("id"), 10, 64)
|
||||
|
||||
Reference in new issue
Block a user