feat: provider presets (openai, openrouter, ollama, dahl, gonkarouter, custom), /api/info, provider display in Android settings
This commit is contained in:
parent
d2ec0848c8
commit
7b92e259ad
14 changed files with 233 additions and 18 deletions
|
|
@ -29,12 +29,22 @@ type Server struct {
|
|||
AllowedOrigins []string
|
||||
Log *slog.Logger
|
||||
RunTimeout time.Duration
|
||||
// Info is returned by GET /api/info (never contains secrets).
|
||||
Info Info
|
||||
}
|
||||
|
||||
type Info struct {
|
||||
Version string `json:"version"`
|
||||
Provider string `json:"provider"`
|
||||
Model string `json:"model"`
|
||||
BaseURL string `json:"base_url"`
|
||||
}
|
||||
|
||||
func (s *Server) Handler() http.Handler {
|
||||
mux := http.NewServeMux()
|
||||
mux.HandleFunc("GET /healthz", func(w http.ResponseWriter, _ *http.Request) { writeJSON(w, 200, map[string]string{"status": "ok"}) })
|
||||
api := http.NewServeMux()
|
||||
api.HandleFunc("GET /api/info", func(w http.ResponseWriter, _ *http.Request) { writeJSON(w, 200, s.Info) })
|
||||
api.HandleFunc("GET /api/sessions", s.listSessions)
|
||||
api.HandleFunc("POST /api/sessions", s.createSession)
|
||||
api.HandleFunc("GET /api/sessions/{id}", s.getSession)
|
||||
|
|
@ -115,7 +125,9 @@ func writeJSON(w http.ResponseWriter, code int, v any) {
|
|||
json.NewEncoder(w).Encode(v)
|
||||
}
|
||||
|
||||
func writeErr(w http.ResponseWriter, code int, msg string) { writeJSON(w, code, map[string]string{"error": msg}) }
|
||||
func writeErr(w http.ResponseWriter, code int, msg string) {
|
||||
writeJSON(w, code, map[string]string{"error": msg})
|
||||
}
|
||||
|
||||
func decode(w http.ResponseWriter, r *http.Request, v any) bool {
|
||||
if err := json.NewDecoder(http.MaxBytesReader(w, r.Body, maxBody)).Decode(v); err != nil {
|
||||
|
|
@ -144,7 +156,9 @@ func (s *Server) listSessions(w http.ResponseWriter, r *http.Request) {
|
|||
}
|
||||
|
||||
func (s *Server) createSession(w http.ResponseWriter, r *http.Request) {
|
||||
var b struct{ Title string `json:"title"` }
|
||||
var b struct {
|
||||
Title string `json:"title"`
|
||||
}
|
||||
if r.ContentLength != 0 && !decode(w, r, &b) {
|
||||
return
|
||||
}
|
||||
|
|
@ -166,7 +180,9 @@ func (s *Server) getSession(w http.ResponseWriter, r *http.Request) {
|
|||
}
|
||||
|
||||
func (s *Server) renameSession(w http.ResponseWriter, r *http.Request) {
|
||||
var b struct{ Title string `json:"title"` }
|
||||
var b struct {
|
||||
Title string `json:"title"`
|
||||
}
|
||||
if !decode(w, r, &b) {
|
||||
return
|
||||
}
|
||||
|
|
|
|||
|
|
@ -39,7 +39,7 @@ func setup(t *testing.T, origins ...string) *httptest.Server {
|
|||
t.Fatal(err)
|
||||
}
|
||||
t.Cleanup(func() { st.Close() })
|
||||
s := &Server{Store: st, Token: tok, AllowedOrigins: origins, Log: slog.New(slog.NewTextHandler(io.Discard, nil)), RunTimeout: 5 * time.Second,
|
||||
s := &Server{Store: st, Token: tok, AllowedOrigins: origins, Log: slog.New(slog.NewTextHandler(io.Discard, nil)), RunTimeout: 5 * time.Second, Info: Info{Provider: "dahl", Model: "MiniMaxAI/MiniMax-M2.7"},
|
||||
Agent: &agent.Agent{LLM: echo{}, Store: st, Tools: tools.NewRegistry(), MaxIterations: 3}}
|
||||
ts := httptest.NewServer(s.Handler())
|
||||
t.Cleanup(ts.Close)
|
||||
|
|
@ -154,3 +154,16 @@ func TestWebSocketStreaming(t *testing.T) {
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
func TestInfo(t *testing.T) {
|
||||
ts := setup(t)
|
||||
if r := do(t, "GET", ts.URL+"/api/info", "", nil); r.StatusCode != 401 {
|
||||
t.Fatal(r.StatusCode)
|
||||
}
|
||||
r := do(t, "GET", ts.URL+"/api/info", "", authH)
|
||||
var i Info
|
||||
json.NewDecoder(r.Body).Decode(&i)
|
||||
if i.Provider != "dahl" || i.Model != "MiniMaxAI/MiniMax-M2.7" {
|
||||
t.Fatalf("%+v", i)
|
||||
}
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue