Files
MonkeyCode/backend/internal/openai/handler/v1/v1.go

193 lines
5.2 KiB
Go
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
package v1
import (
"fmt"
"log/slog"
"net/http"
"github.com/labstack/echo/v4"
"github.com/GoYoko/web"
"github.com/chaitin/MonkeyCode/backend/config"
"github.com/chaitin/MonkeyCode/backend/domain"
"github.com/chaitin/MonkeyCode/backend/internal/middleware"
"github.com/chaitin/MonkeyCode/backend/internal/proxy"
"github.com/chaitin/MonkeyCode/backend/pkg/request"
)
type V1Handler struct {
logger *slog.Logger
proxy *proxy.LLMProxy
proxyUse domain.ProxyUsecase
usecase domain.OpenAIUsecase
euse domain.ExtensionUsecase
config *config.Config
}
func NewV1Handler(
logger *slog.Logger,
w *web.Web,
proxy *proxy.LLMProxy,
proxyUse domain.ProxyUsecase,
usecase domain.OpenAIUsecase,
euse domain.ExtensionUsecase,
middleware *middleware.ProxyMiddleware,
active *middleware.ActiveMiddleware,
config *config.Config,
) *V1Handler {
h := &V1Handler{
logger: logger.With(slog.String("handler", "openai")),
proxy: proxy,
proxyUse: proxyUse,
usecase: usecase,
euse: euse,
config: config,
}
w.GET("/api/config", web.BindHandler(h.GetConfig), middleware.Auth())
w.GET("/v1/version", web.BaseHandler(h.Version), middleware.Auth())
g := w.Group("/v1", middleware.Auth())
g.GET("/models", web.BaseHandler(h.ModelList))
g.POST("/completion/accept", web.BindHandler(h.AcceptCompletion), active.Active("apikey"))
g.POST("/report", web.BindHandler(h.Report), active.Active("apikey"))
g.POST("/chat/completions", web.BaseHandler(h.ChatCompletion), active.Active("apikey"))
g.POST("/completions", web.BaseHandler(h.Completions), active.Active("apikey"))
g.POST("/embeddings", web.BaseHandler(h.Embeddings), active.Active("apikey"))
return h
}
func BadRequest(c *web.Context, msg string) error {
c.JSON(http.StatusBadRequest, echo.Map{
"error": echo.Map{
"message": msg,
"type": "invalid_request_error",
},
})
return nil
}
func (h *V1Handler) Version(c *web.Context) error {
v, err := h.euse.Latest(c.Request().Context())
if err != nil {
return err
}
return c.JSON(http.StatusOK, domain.VersionInfo{
Version: v.Version,
URL: fmt.Sprintf("%s/api/v1/static/vsix/%s", request.GetBaseURL(c.Request()), v.Version),
})
}
// AcceptCompletion 接受补全请求
//
// @Tags OpenAIV1
// @Summary 接受补全请求
// @Description 接受补全请求
// @ID accept-completion
// @Accept json
// @Produce json
// @Param param body domain.AcceptCompletionReq true "补全请求"
// @Success 200 {object} web.Resp{}
// @Router /v1/completion/accept [post]
func (h *V1Handler) AcceptCompletion(c *web.Context, req domain.AcceptCompletionReq) error {
if err := h.proxyUse.AcceptCompletion(c.Request().Context(), &req); err != nil {
return BadRequest(c, err.Error())
}
return nil
}
// Report 报告
//
// @Tags OpenAIV1
// @Summary 报告
// @Description 报告支持多种操作accept接受补全、suggest建议、reject拒绝补全并记录用户输入、file_written文件写入
// @ID report
// @Accept json
// @Produce json
// @Param param body domain.ReportReq true "报告请求"
// @Success 200 {object} web.Resp{}
// @Router /v1/report [post]
func (h *V1Handler) Report(c *web.Context, req domain.ReportReq) error {
h.logger.DebugContext(c.Request().Context(), "Report", slog.Any("req", req))
if err := h.proxyUse.Report(c.Request().Context(), &req); err != nil {
return err
}
return c.Success(nil)
}
// ModelList 模型列表
//
// @Tags OpenAIV1
// @Summary 模型列表
// @Description 模型列表
// @ID model-list
// @Accept json
// @Produce json
// @Success 200 {object} web.Resp{data=domain.ModelListResp}
// @Router /v1/models [get]
func (h *V1Handler) ModelList(c *web.Context) error {
resp, err := h.usecase.ModelList(c.Request().Context())
if err != nil {
return err
}
return c.Success(resp)
}
// ChatCompletion 处理聊天补全请求
//
// @Tags OpenAIV1
// @Summary 处理聊天补全请求
// @Description 处理聊天补全请求
// @ID chat-completion
// @Accept json
// @Produce json
// @Success 200 {object} web.Resp{}
// @Router /v1/chat/completions [post]
func (h *V1Handler) ChatCompletion(c *web.Context) error {
h.proxy.ServeHTTP(c.Response(), c.Request())
return nil
}
// Completions 处理文本补全请求
//
// @Tags OpenAIV1
// @Summary 处理文本补全请求
// @Description 处理文本补全请求
// @ID completions
// @Accept json
// @Produce json
// @Success 200 {object} web.Resp{}
// @Router /v1/completions [post]
func (h *V1Handler) Completions(c *web.Context) error {
h.proxy.ServeHTTP(c.Response(), c.Request())
return nil
}
// Embeddings 处理嵌入请求
//
// @Tags OpenAIV1
// @Summary 处理嵌入请求
// @Description 处理嵌入请求
// @ID embeddings
// @Accept json
// @Produce json
// @Success 200 {object} web.Resp{}
// @Router /v1/embeddings [post]
func (h *V1Handler) Embeddings(c *web.Context) error {
h.proxy.ServeHTTP(c.Response(), c.Request())
return nil
}
func (h *V1Handler) GetConfig(c *web.Context, req domain.ConfigReq) error {
key := middleware.GetApiKey(c)
req.Key = key.Key
req.BaseURL = request.GetBaseURL(c.Request())
resp, err := h.usecase.GetConfig(c.Request().Context(), &req)
if err != nil {
return err
}
return c.JSON(http.StatusOK, resp)
}