package api import ( "encoding/json" "net/http" "github.com/go-chi/chi/v5" "github.com/local-mcp/local-mcp-go/internal/events" "github.com/local-mcp/local-mcp-go/internal/store" ) func handleListInstructions(stores Stores) http.HandlerFunc { return func(w http.ResponseWriter, r *http.Request) { status := r.URL.Query().Get("status") if status == "" { status = "all" } items, err := stores.Instructions.List(status) if err != nil { writeError(w, http.StatusInternalServerError, err.Error()) return } writeJSON(w, http.StatusOK, map[string]any{"items": items}) } } func handleCreateInstruction(stores Stores, broker *events.Broker) http.HandlerFunc { return func(w http.ResponseWriter, r *http.Request) { var body struct { Content string `json:"content"` } if err := json.NewDecoder(r.Body).Decode(&body); err != nil { writeError(w, http.StatusBadRequest, "Invalid JSON") return } if body.Content == "" { writeError(w, http.StatusBadRequest, "content is required") return } item, err := stores.Instructions.Create(body.Content) if err != nil { writeError(w, http.StatusInternalServerError, err.Error()) return } counts, _ := stores.Instructions.Counts() broker.Broadcast("instruction.created", map[string]any{"item": item}) broker.Broadcast("status.changed", map[string]any{"queue": counts}) writeJSON(w, http.StatusCreated, item) } } func handleUpdateInstruction(stores Stores, broker *events.Broker) http.HandlerFunc { return func(w http.ResponseWriter, r *http.Request) { id := chi.URLParam(r, "id") var body struct { Content string `json:"content"` } if err := json.NewDecoder(r.Body).Decode(&body); err != nil { writeError(w, http.StatusBadRequest, "Invalid JSON") return } item, err := stores.Instructions.Update(id, body.Content) if err == store.ErrNotFound { writeError(w, http.StatusNotFound, "Instruction not found") return } if err == store.ErrAlreadyConsumed { writeError(w, http.StatusConflict, "Cannot edit consumed instruction") return } if err != nil { writeError(w, http.StatusInternalServerError, err.Error()) return } broker.Broadcast("instruction.updated", map[string]any{"item": item}) writeJSON(w, http.StatusOK, item) } } func handleDeleteInstruction(stores Stores, broker *events.Broker) http.HandlerFunc { return func(w http.ResponseWriter, r *http.Request) { id := chi.URLParam(r, "id") if err := stores.Instructions.Delete(id); err == store.ErrNotFound { writeError(w, http.StatusNotFound, "Instruction not found") return } else if err == store.ErrAlreadyConsumed { writeError(w, http.StatusConflict, "Cannot delete consumed instruction") return } else if err != nil { writeError(w, http.StatusInternalServerError, err.Error()) return } counts, _ := stores.Instructions.Counts() broker.Broadcast("instruction.deleted", map[string]any{"id": id}) broker.Broadcast("status.changed", map[string]any{"queue": counts}) w.WriteHeader(http.StatusNoContent) } } func handleClearConsumed(stores Stores, broker *events.Broker) http.HandlerFunc { return func(w http.ResponseWriter, r *http.Request) { items, err := stores.Instructions.List("consumed") if err != nil { writeError(w, http.StatusInternalServerError, err.Error()) return } if err := stores.Instructions.DeleteConsumed(); err != nil { writeError(w, http.StatusInternalServerError, err.Error()) return } counts, _ := stores.Instructions.Counts() cleared := len(items) broker.Broadcast("history.cleared", map[string]any{"count": cleared}) broker.Broadcast("status.changed", map[string]any{"queue": counts}) writeJSON(w, http.StatusOK, map[string]any{"cleared": cleared}) } }