From afcb75940ce2bea0decedc9ccd395a2675fda4ff Mon Sep 17 00:00:00 2001 From: Philip Zeyliger Date: Mon, 2 Feb 2026 16:54:51 -0800 Subject: [PATCH] shelley: /debug/conversations page with CSV export for token visualization Prompt: I want a /debug/conversations view in Shelley which is just a list of conversations (with their slugs), with a way to download a compatible CSV of message costs. - Add /debug/conversations route - Lists all conversations with slug, date, message count - Searchable by slug - Download CSV button for each conversation - CSV format: input_tokens,cache_write_tokens,cache_read_tokens,output_tokens - CSV can be used with standalone token spend visualizer Co-authored-by: Shelley --- server/debug_handlers.go | 18 ++++ server/server.go | 1 + ui/public/conversations.html | 194 +++++++++++++++++++++++++++++++++++ 3 files changed, 213 insertions(+) create mode 100644 ui/public/conversations.html diff --git a/server/debug_handlers.go b/server/debug_handlers.go index e8a7d464a85aa093a54966779ca0644a2e10ed41..e4efa6f3c9dea1f4fdff2ec86651827507798f3d 100644 --- a/server/debug_handlers.go +++ b/server/debug_handlers.go @@ -2,10 +2,28 @@ package server import ( "encoding/json" + "io" "net/http" "strconv" + + "shelley.exe.dev/ui" ) +// handleDebugConversationsPage serves the conversations list debug page +func (s *Server) handleDebugConversationsPage(w http.ResponseWriter, r *http.Request) { + fsys := ui.Assets() + file, err := fsys.Open("/conversations.html") + if err != nil { + http.Error(w, "conversations.html not found", http.StatusNotFound) + return + } + defer file.Close() + + w.Header().Set("Content-Type", "text/html") + w.Header().Set("Cache-Control", "no-cache, no-store, must-revalidate") + io.Copy(w, file) +} + // handleDebugLLMRequests serves the debug page for LLM requests func (s *Server) handleDebugLLMRequests(w http.ResponseWriter, r *http.Request) { w.Header().Set("Content-Type", "text/html") diff --git a/server/server.go b/server/server.go index 1cc08dada95c66b789cf89a57b2c622cbb2e710b..1e3924eb5da2974e028de88e397bf353e0968652 100644 --- a/server/server.go +++ b/server/server.go @@ -285,6 +285,7 @@ func (s *Server) RegisterRoutes(mux *http.ServeMux) { mux.Handle("POST /exit", http.HandlerFunc(s.handleExit)) // Debug endpoints + mux.Handle("GET /debug/conversations", http.HandlerFunc(s.handleDebugConversationsPage)) mux.Handle("GET /debug/llm_requests", http.HandlerFunc(s.handleDebugLLMRequests)) mux.Handle("GET /debug/llm_requests/api", http.HandlerFunc(s.handleDebugLLMRequestsAPI)) mux.Handle("GET /debug/llm_requests/{id}/request", http.HandlerFunc(s.handleDebugLLMRequestBody)) diff --git a/ui/public/conversations.html b/ui/public/conversations.html new file mode 100644 index 0000000000000000000000000000000000000000..245f3a46b02e3a015e53fb9f4d9f8b23648b572d --- /dev/null +++ b/ui/public/conversations.html @@ -0,0 +1,194 @@ + + + + + + Debug: Conversations + + + +

Conversations

+ + + + + + + + + + + + + + +
SlugCreatedActions
Loading...
+ +
+ CSV Format: input_tokens,cache_write_tokens,cache_read_tokens,output_tokens
+ One row per agent message. Use with the standalone Token Spend Visualizer. +
+ + + +