byteclaw/internal/server/extra.go

150 lines
3.6 KiB
Go

package server
import (
"errors"
"net/http"
"github.com/crypto/byteclaw/internal/providers"
"github.com/crypto/byteclaw/internal/store"
)
func (s *Server) info(w http.ResponseWriter, _ *http.Request) {
in := s.Info
if s.Providers != nil {
a := s.Providers.Active()
in.Provider, in.Model, in.BaseURL = a.Provider, a.Model, s.Providers.BaseURL(a.Provider)
}
writeJSON(w, 200, in)
}
func (s *Server) needProviders(w http.ResponseWriter) bool {
if s.Providers == nil {
writeErr(w, http.StatusNotImplemented, "provider switching not enabled")
return false
}
return true
}
func providerErr(w http.ResponseWriter, err error) {
switch {
case errors.Is(err, providers.ErrUnknown):
writeErr(w, http.StatusNotFound, err.Error())
default:
writeErr(w, http.StatusBadRequest, err.Error())
}
}
type providerReq struct {
Provider string `json:"provider"`
Model string `json:"model"`
}
// GET /api/providers -> {"active":{...},"providers":[...]} (never contains keys).
func (s *Server) listProviders(w http.ResponseWriter, _ *http.Request) {
if !s.needProviders(w) {
return
}
writeJSON(w, 200, map[string]any{"active": s.Providers.Active(), "providers": s.Providers.List()})
}
func (s *Server) setActiveProvider(w http.ResponseWriter, r *http.Request) {
if !s.needProviders(w) {
return
}
var b providerReq
if !decode(w, r, &b) {
return
}
a, err := s.Providers.SetActive(r.Context(), b.Provider, b.Model)
if err != nil {
providerErr(w, err)
return
}
writeJSON(w, 200, a)
}
func (s *Server) listModels(w http.ResponseWriter, r *http.Request) {
if !s.needProviders(w) {
return
}
ids, err := s.Providers.Models(r.Context(), r.PathValue("name"))
if errors.Is(err, providers.ErrUnknown) {
providerErr(w, err)
return
}
if err != nil {
s.Log.Warn("list models", "err", err)
writeErr(w, http.StatusBadGateway, "provider does not offer a model list")
return
}
writeJSON(w, 200, map[string]any{"models": ids})
}
// PUT /api/sessions/{id}/provider: per-session override; empty provider clears it.
func (s *Server) setSessionProvider(w http.ResponseWriter, r *http.Request) {
if !s.needProviders(w) {
return
}
var b providerReq
if !decode(w, r, &b) {
return
}
id := r.PathValue("id")
if !s.owns(w, r, id) {
return
}
var a providers.Active
if b.Provider != "" {
var err error
if a, err = s.Providers.Validate(b.Provider, b.Model); err != nil {
providerErr(w, err)
return
}
}
if err := s.Store.SetSessionProvider(r.Context(), id, a.Provider, a.Model); err != nil {
s.storeErr(w, err)
return
}
writeJSON(w, 200, a)
}
func (s *Server) cancel(w http.ResponseWriter, r *http.Request) {
if !s.owns(w, r, r.PathValue("id")) {
return
}
writeJSON(w, 200, map[string]bool{"cancelled": s.Agent.Cancel(r.PathValue("id"))})
}
func (s *Server) summarize(w http.ResponseWriter, r *http.Request) {
id := r.PathValue("id")
if !s.owns(w, r, id) {
return
}
sm, err := s.Agent.SummarizeNow(r.Context(), id)
if err != nil {
s.Log.Warn("summarize", "err", err)
writeErr(w, http.StatusBadGateway, err.Error())
return
}
if sm == nil {
writeJSON(w, 200, map[string]any{"summary": nil, "note": "nothing to summarize yet"})
return
}
writeJSON(w, 200, map[string]any{"summary": sm})
}
func (s *Server) getSummary(w http.ResponseWriter, r *http.Request) {
if !s.owns(w, r, r.PathValue("id")) {
return
}
sm, err := s.Store.LatestSummary(r.Context(), r.PathValue("id"))
if err != nil {
if errors.Is(err, store.ErrNotFound) {
writeErr(w, http.StatusNotFound, "no summary")
return
}
s.storeErr(w, err)
return
}
writeJSON(w, 200, sm)
}