package handler import ( "fmt" "net/http" "github.com/go-chi/chi/v5" "github.com/anotherhadi/iknowyou/internal/respond" "github.com/anotherhadi/iknowyou/internal/tools" ) type ToolsHandler struct { factories []func() tools.ToolRunner } func NewToolsHandler(factories []func() tools.ToolRunner) *ToolsHandler { return &ToolsHandler{factories: factories} } type toolInfo struct { Name string `json:"name"` Description string `json:"description"` Link string `json:"link,omitempty"` Icon string `json:"icon,omitempty"` InputTypes []tools.InputType `json:"input_types"` Configurable bool `json:"configurable"` ConfigFields []tools.ConfigField `json:"config_fields,omitempty"` Available *bool `json:"available,omitempty"` UnavailableReason string `json:"unavailable_reason,omitempty"` Dependencies []string `json:"dependencies,omitempty"` } func toToolInfo(t tools.ToolRunner) toolInfo { _, configurable := t.(tools.Configurable) var fields []tools.ConfigField if d, ok := t.(tools.ConfigDescriber); ok { fields = d.ConfigFields() } var available *bool var unavailableReason string if checker, ok := t.(tools.AvailabilityChecker); ok { avail, reason := checker.Available() available = &avail if !avail { unavailableReason = reason } } var dependencies []string if lister, ok := t.(tools.DependencyLister); ok { dependencies = lister.Dependencies() } return toolInfo{ Name: t.Name(), Description: t.Description(), Link: t.Link(), Icon: t.Icon(), InputTypes: t.InputTypes(), Configurable: configurable, ConfigFields: fields, Available: available, UnavailableReason: unavailableReason, Dependencies: dependencies, } } // GET /api/tools func (h *ToolsHandler) List(w http.ResponseWriter, r *http.Request) { infos := make([]toolInfo, 0, len(h.factories)) for _, factory := range h.factories { infos = append(infos, toToolInfo(factory())) } respond.JSON(w, http.StatusOK, infos) } // GET /api/tools/{name} func (h *ToolsHandler) Get(w http.ResponseWriter, r *http.Request) { name := chi.URLParam(r, "name") for _, factory := range h.factories { t := factory() if t.Name() == name { respond.JSON(w, http.StatusOK, toToolInfo(t)) return } } respond.Error(w, http.StatusNotFound, fmt.Sprintf("tool %q not found", name)) }