146 lines
3.6 KiB
Go
146 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 _, err := s.Store.GetSession(r.Context(), id); err != nil {
|
|
s.storeErr(w, err)
|
|
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) {
|
|
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 _, err := s.Store.GetSession(r.Context(), id); err != nil {
|
|
s.storeErr(w, err)
|
|
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) {
|
|
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)
|
|
}
|