feat(commands): 工具执行页新增调用次数统计
「工具执行」页工具栏加「统计」按钮,弹窗按工具展示调用次数、占比与 失败次数,按次数降序。统计沿用列表的 task/q 筛选,算的是整个结果集 而非当前页;弹窗打开时才请求,翻页不会多付一次聚合查询。 - db: 抽出 commandFilter,列表与统计共用同一份 WHERE;新增 ToolStats - server: GET /api/commands/stats - web: 统计弹窗 + demo 模式 mock
This commit is contained in:
1 parent
a380eb4195
commit
e10f8413dc
7 files changed
+207
-22
No files matched your search
+32
-8
@@ -15,14 +15,7 @@ func (s *Server) pgListCommands(w http.ResponseWriter, r *http.Request) {
|
||||
size := atoiDefault(q.Get("size"), 50)
|
||||
keyword := q.Get("q")
|
||||
|
||||
var expID *int64
|
||||
if tv := q.Get("task"); tv != "" {
|
||||
if n, err := strconv.ParseInt(tv, 10, 64); err == nil {
|
||||
expID = &n
|
||||
}
|
||||
}
|
||||
|
||||
records, total, err := s.m.PG().ListCommands(expID, keyword, page, size)
|
||||
records, total, err := s.m.PG().ListCommands(commandTaskFilter(q.Get("task")), keyword, page, size)
|
||||
if err != nil {
|
||||
writeErr(w, 500, err.Error())
|
||||
return
|
||||
@@ -30,6 +23,37 @@ func (s *Server) pgListCommands(w http.ResponseWriter, r *http.Request) {
|
||||
writeJSON(w, 200, map[string]any{"commands": records, "total": total})
|
||||
}
|
||||
|
||||
// pgToolStats returns per-tool call counts for the tool-execution history, under
|
||||
// the same task/keyword filters the list takes — the summary describes the whole
|
||||
// filtered set, not the page on screen.
|
||||
func (s *Server) pgToolStats(w http.ResponseWriter, r *http.Request) {
|
||||
q := r.URL.Query()
|
||||
pg := s.m.PG()
|
||||
if pg == nil {
|
||||
writeJSON(w, 200, map[string]any{"stats": []db.ToolStat{}})
|
||||
return
|
||||
}
|
||||
stats, err := pg.ToolStats(commandTaskFilter(q.Get("task")), q.Get("q"))
|
||||
if err != nil {
|
||||
writeErr(w, 500, err.Error())
|
||||
return
|
||||
}
|
||||
writeJSON(w, 200, map[string]any{"stats": stats})
|
||||
}
|
||||
|
||||
// commandTaskFilter parses the ?task= exploration id. Absent or unparsable → nil
|
||||
// (no filter), matching the list endpoint's long-standing lenient behaviour.
|
||||
func commandTaskFilter(v string) *int64 {
|
||||
if v == "" {
|
||||
return nil
|
||||
}
|
||||
n, err := strconv.ParseInt(v, 10, 64)
|
||||
if err != nil {
|
||||
return nil
|
||||
}
|
||||
return &n
|
||||
}
|
||||
|
||||
// pgListLLMRecords returns paginated LLM call records.
|
||||
func (s *Server) pgListLLMRecords(w http.ResponseWriter, r *http.Request) {
|
||||
q := r.URL.Query()
|
||||
|
||||
@@ -787,6 +787,7 @@ func (s *Server) Handler() http.Handler {
|
||||
mux.HandleFunc("GET /api/traffic/exchange", s.getTrafficExchange)
|
||||
mux.HandleFunc("GET /api/traffic/blob", s.getTrafficBlob)
|
||||
mux.HandleFunc("GET /api/commands", s.pgListCommands)
|
||||
mux.HandleFunc("GET /api/commands/stats", s.pgToolStats) // 按工具聚合调用次数
|
||||
mux.HandleFunc("GET /api/llm/records", s.pgListLLMRecords)
|
||||
mux.HandleFunc("DELETE /api/llm/records", s.pgDeleteLLMRecords)
|
||||
mux.HandleFunc("GET /api/llm/records/tasks", s.pgLLMTasks)
|
||||
|
||||
Reference in new issue
Block a user