mirror of
https://github.com/CJackHwang/ds2api.git
synced 2026-05-12 20:27:43 +08:00
Add ollama api for copilot support
This commit is contained in:
53
internal/httpapi/ollama/handler_routes.go
Normal file
53
internal/httpapi/ollama/handler_routes.go
Normal file
@@ -0,0 +1,53 @@
|
||||
package ollama
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"net/http"
|
||||
"github.com/go-chi/chi/v5"
|
||||
"ds2api/internal/config"
|
||||
"ds2api/internal/util"
|
||||
)
|
||||
|
||||
var WriteJSON = util.WriteJSON
|
||||
|
||||
type ConfigReader interface {
|
||||
ModelAliases() map[string]string
|
||||
}
|
||||
|
||||
type Handler struct {
|
||||
Store ConfigReader
|
||||
}
|
||||
|
||||
type OllamaModelRequest struct {
|
||||
Model string `json:"model"`
|
||||
}
|
||||
|
||||
func RegisterRoutes(r chi.Router, h *Handler) {
|
||||
r.Get("/api/version", h.GetVersion)
|
||||
r.Get("/api/tags", h.ListOllamaModels)
|
||||
r.Post("/api/show", h.GetOllamaModel)
|
||||
}
|
||||
|
||||
func (h *Handler) GetVersion(w http.ResponseWriter, r *http.Request) {
|
||||
w.Header().Set("Content-Type", "application/json")
|
||||
w.WriteHeader(http.StatusOK)
|
||||
_, _ = w.Write([]byte(`{"version":"0.23.1"}`))
|
||||
}
|
||||
func (h *Handler) ListOllamaModels(w http.ResponseWriter, r *http.Request) {
|
||||
WriteJSON(w, http.StatusOK, config.OllamaModelsResponse())
|
||||
}
|
||||
func (h *Handler) GetOllamaModel(w http.ResponseWriter, r *http.Request) {
|
||||
var payload OllamaModelRequest
|
||||
if err := json.NewDecoder(r.Body).Decode(&payload); err != nil {
|
||||
http.Error(w, "Invalid JSON body: "+err.Error(), http.StatusBadRequest)
|
||||
return
|
||||
}
|
||||
defer r.Body.Close()
|
||||
modelID := payload.Model
|
||||
model, ok := config.OllamaModelByID(h.Store, modelID)
|
||||
if !ok {
|
||||
http.Error(w, "Model not found.", http.StatusNotFound)
|
||||
return
|
||||
}
|
||||
WriteJSON(w, http.StatusOK, model)
|
||||
}
|
||||
122
internal/httpapi/ollama/handler_routes_test.go
Normal file
122
internal/httpapi/ollama/handler_routes_test.go
Normal file
@@ -0,0 +1,122 @@
|
||||
package ollama
|
||||
|
||||
import (
|
||||
"net/http"
|
||||
"net/http/httptest"
|
||||
"testing"
|
||||
|
||||
"github.com/go-chi/chi/v5"
|
||||
)
|
||||
|
||||
type ollamaTestSurface struct {
|
||||
Store shared.ConfigReader
|
||||
handler *Handler
|
||||
}
|
||||
|
||||
GetVersion(w http.ResponseWriter, r *http.Request) {
|
||||
w.Header().Set("Content-Type", "application/json")
|
||||
w.WriteHeader(http.StatusOK)
|
||||
_, _ = w.Write([]byte(`{"version":"0.23.1"}`))
|
||||
}
|
||||
func (h *Handler) ListOllamaModels(w http.ResponseWriter, r *http.Request) {
|
||||
WriteJSON(w, http.StatusOK, config.OllamaModelsResponse())
|
||||
}
|
||||
func (h *Handler) GetOllamaModel
|
||||
|
||||
func registerOllamaTestRoutes(r chi.Router, h *ollamaTestSurface) {
|
||||
r.Get("/api/version", h.handler().GetVersion)
|
||||
r.Get("/api/tags", h.modelsHandler().ListOllamaModels)
|
||||
r.Post("/api/show", h.chatHandler().GetOllamaModel)
|
||||
}
|
||||
|
||||
|
||||
func TestGetOllamaVersionRoute(t *testing.T) {
|
||||
h := &ollamaTestSurface{}
|
||||
r := chi.NewRouter()
|
||||
registerOllamaTestRoutes(r, h)
|
||||
req := httptest.NewRequest(http.MethodGet, "/api/version", nil)
|
||||
rec := httptest.NewRecorder()
|
||||
r.ServeHTTP(rec, req)
|
||||
if rec.Code != http.StatusOK {
|
||||
t.Fatalf("expected 200, got %d body=%s", rec.Code, rec.Body.String())
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
func TestGetOllamaModelsRoute(t *testing.T) {
|
||||
h := &ollamaTestSurface{}
|
||||
r := chi.NewRouter()
|
||||
registerOllamaTestRoutes(r, h)
|
||||
req := httptest.NewRequest(http.MethodGet, "/api/tags", nil)
|
||||
rec := httptest.NewRecorder()
|
||||
r.ServeHTTP(rec, req)
|
||||
if rec.Code != http.StatusOK {
|
||||
t.Fatalf("expected 200, got %d body=%s", rec.Code, rec.Body.String())
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
func TestGetOllamaModelRoute(t *testing.T) {
|
||||
h := &ollamaTestSurface{}
|
||||
r := chi.NewRouter()
|
||||
registerOllamaTestRoutes(r, h)
|
||||
|
||||
t.Run("direct", func(t *testing.T) {
|
||||
body := `{"model":"deepseek-v4-flash"}`
|
||||
req := httptest.NewRequest(http.MethodPost, "/api/show", strings.NewReader(body))
|
||||
req.Header.Set("Content-Type", "application/json")
|
||||
rec := httptest.NewRecorder()
|
||||
r.ServeHTTP(rec, req)
|
||||
if rec.Code != http.StatusOK {
|
||||
t.Fatalf("expected 200, got %d body=%s", rec.Code, rec.Body.String())
|
||||
}
|
||||
})
|
||||
|
||||
t.Run("direct_nothinking", func(t *testing.T) {
|
||||
body := `{"model":"deepseek-v4-flash-nothinking"}`
|
||||
req := httptest.NewRequest(http.MethodPost, "/api/show", strings.NewReader(body))
|
||||
req.Header.Set("Content-Type", "application/json")
|
||||
rec := httptest.NewRecorder()
|
||||
r.ServeHTTP(rec, req)
|
||||
if rec.Code != http.StatusOK {
|
||||
t.Fatalf("expected 200, got %d body=%s", rec.Code, rec.Body.String())
|
||||
}
|
||||
})
|
||||
|
||||
t.Run("direct_expert", func(t *testing.T) {
|
||||
body := `{"model":"models/deepseek-v4-pro"}`
|
||||
req := httptest.NewRequest(http.MethodPost, "/api/show", strings.NewReader(body))
|
||||
req.Header.Set("Content-Type", "application/json")
|
||||
rec := httptest.NewRecorder()
|
||||
r.ServeHTTP(rec, req)
|
||||
if rec.Code != http.StatusOK {
|
||||
t.Fatalf("expected 200, got %d body=%s", rec.Code, rec.Body.String())
|
||||
}
|
||||
})
|
||||
|
||||
t.Run("direct_vision", func(t *testing.T) {
|
||||
body := `{"model":"deepseek-v4-vision"}`
|
||||
req := httptest.NewRequest(http.MethodPost, "/api/show", strings.NewReader(body))
|
||||
req.Header.Set("Content-Type", "application/json")
|
||||
rec := httptest.NewRecorder()
|
||||
r.ServeHTTP(rec, req)
|
||||
if rec.Code != http.StatusOK {
|
||||
t.Fatalf("expected 200, got %d body=%s", rec.Code, rec.Body.String())
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
func TestGetOllamaModelRouteNotFound(t *testing.T) {
|
||||
h := &ollamaTestSurface{}
|
||||
r := chi.NewRouter()
|
||||
registerOllamaTestRoutes(r, h)
|
||||
|
||||
body := `{"model":"not-exists"}`
|
||||
req := httptest.NewRequest(http.MethodPost, "/api/show", strings.NewReader(body))
|
||||
req.Header.Set("Content-Type", "application/json")
|
||||
rec := httptest.NewRecorder()
|
||||
r.ServeHTTP(rec, req)
|
||||
if rec.Code != http.StatusNotFound {
|
||||
t.Fatalf("expected 404, got %d body=%s", rec.Code, rec.Body.String())
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user