180 lines
5.8 KiB
Go
180 lines
5.8 KiB
Go
package grpc
|
|
|
|
import (
|
|
"context"
|
|
"errors"
|
|
|
|
"google.golang.org/protobuf/types/known/timestamppb"
|
|
|
|
conversationv1 "enkly/gen/conversation/v1"
|
|
"enkly/pkg/grpcerr"
|
|
"enkly/services/conversation/internal/application"
|
|
"enkly/services/conversation/internal/domain"
|
|
)
|
|
|
|
type Server struct {
|
|
conversationv1.UnimplementedConversationServiceServer
|
|
Svc *application.Service
|
|
}
|
|
|
|
func New(svc *application.Service) *Server { return &Server{Svc: svc} }
|
|
|
|
func toProtoRole(r domain.Role) conversationv1.Role {
|
|
switch r {
|
|
case domain.RoleUser:
|
|
return conversationv1.Role_ROLE_USER
|
|
case domain.RoleAssistant:
|
|
return conversationv1.Role_ROLE_ASSISTANT
|
|
case domain.RoleSystem:
|
|
return conversationv1.Role_ROLE_SYSTEM
|
|
case domain.RoleTool:
|
|
return conversationv1.Role_ROLE_TOOL
|
|
default:
|
|
return conversationv1.Role_ROLE_UNSPECIFIED
|
|
}
|
|
}
|
|
|
|
func fromProtoRole(r conversationv1.Role) domain.Role {
|
|
switch r {
|
|
case conversationv1.Role_ROLE_USER:
|
|
return domain.RoleUser
|
|
case conversationv1.Role_ROLE_ASSISTANT:
|
|
return domain.RoleAssistant
|
|
case conversationv1.Role_ROLE_SYSTEM:
|
|
return domain.RoleSystem
|
|
case conversationv1.Role_ROLE_TOOL:
|
|
return domain.RoleTool
|
|
default:
|
|
return domain.RoleUser
|
|
}
|
|
}
|
|
|
|
func toProtoConversation(c *domain.Conversation) *conversationv1.Conversation {
|
|
return &conversationv1.Conversation{
|
|
Id: c.ID,
|
|
UserId: c.UserID,
|
|
Title: c.Title,
|
|
CreatedAt: timestamppb.New(c.CreatedAt),
|
|
LastMessageAt: timestamppb.New(c.LastMessageAt),
|
|
}
|
|
}
|
|
|
|
func toProtoMessage(m *domain.Message) *conversationv1.Message {
|
|
return &conversationv1.Message{
|
|
Id: m.ID,
|
|
ConversationId: m.ConversationID,
|
|
Role: toProtoRole(m.Role),
|
|
Content: m.Content,
|
|
ToolName: m.ToolName,
|
|
CreatedAt: timestamppb.New(m.CreatedAt),
|
|
}
|
|
}
|
|
|
|
func mapErr(err error) error {
|
|
if errors.Is(err, domain.ErrNotFound) {
|
|
return grpcerr.NotFound("conversation")
|
|
}
|
|
return grpcerr.Internal(err)
|
|
}
|
|
|
|
func (s *Server) CreateConversation(ctx context.Context, req *conversationv1.CreateConversationRequest) (*conversationv1.Conversation, error) {
|
|
c, err := s.Svc.CreateConversation(ctx, req.GetUserId(), req.GetTitle())
|
|
if err != nil {
|
|
return nil, mapErr(err)
|
|
}
|
|
return toProtoConversation(c), nil
|
|
}
|
|
|
|
func (s *Server) GetConversation(ctx context.Context, req *conversationv1.GetConversationRequest) (*conversationv1.Conversation, error) {
|
|
c, err := s.Svc.GetConversation(ctx, req.GetUserId(), req.GetConversationId())
|
|
if err != nil {
|
|
return nil, mapErr(err)
|
|
}
|
|
return toProtoConversation(c), nil
|
|
}
|
|
|
|
func (s *Server) ListConversations(ctx context.Context, req *conversationv1.ListConversationsRequest) (*conversationv1.ListConversationsResponse, error) {
|
|
list, err := s.Svc.ListConversations(ctx, req.GetUserId())
|
|
if err != nil {
|
|
return nil, grpcerr.Internal(err)
|
|
}
|
|
resp := &conversationv1.ListConversationsResponse{}
|
|
for _, c := range list {
|
|
resp.Conversations = append(resp.Conversations, toProtoConversation(c))
|
|
}
|
|
return resp, nil
|
|
}
|
|
|
|
func (s *Server) MostRecentConversation(ctx context.Context, req *conversationv1.MostRecentConversationRequest) (*conversationv1.Conversation, error) {
|
|
c, err := s.Svc.MostRecentConversation(ctx, req.GetUserId())
|
|
if err != nil {
|
|
return nil, mapErr(err)
|
|
}
|
|
return toProtoConversation(c), nil
|
|
}
|
|
|
|
func (s *Server) RenameConversation(ctx context.Context, req *conversationv1.RenameConversationRequest) (*conversationv1.Conversation, error) {
|
|
c, err := s.Svc.RenameConversation(ctx, req.GetUserId(), req.GetConversationId(), req.GetTitle())
|
|
if err != nil {
|
|
return nil, mapErr(err)
|
|
}
|
|
return toProtoConversation(c), nil
|
|
}
|
|
|
|
func (s *Server) AutoTitleConversation(ctx context.Context, req *conversationv1.AutoTitleConversationRequest) (*conversationv1.AutoTitleConversationResponse, error) {
|
|
changed, err := s.Svc.AutoTitleConversation(ctx, req.GetUserId(), req.GetConversationId(), req.GetTitle())
|
|
if err != nil {
|
|
return nil, grpcerr.Internal(err)
|
|
}
|
|
return &conversationv1.AutoTitleConversationResponse{Retitled: changed}, nil
|
|
}
|
|
|
|
func (s *Server) DeleteConversation(ctx context.Context, req *conversationv1.DeleteConversationRequest) (*conversationv1.DeleteConversationResponse, error) {
|
|
if err := s.Svc.DeleteConversation(ctx, req.GetUserId(), req.GetConversationId()); err != nil {
|
|
return nil, mapErr(err)
|
|
}
|
|
return &conversationv1.DeleteConversationResponse{}, nil
|
|
}
|
|
|
|
func (s *Server) CountMessages(ctx context.Context, req *conversationv1.CountMessagesRequest) (*conversationv1.CountMessagesResponse, error) {
|
|
n, err := s.Svc.CountMessages(ctx, req.GetConversationId())
|
|
if err != nil {
|
|
return nil, grpcerr.Internal(err)
|
|
}
|
|
return &conversationv1.CountMessagesResponse{Count: int32(n)}, nil
|
|
}
|
|
|
|
func (s *Server) AddMessage(ctx context.Context, req *conversationv1.AddMessageRequest) (*conversationv1.Message, error) {
|
|
m, err := s.Svc.AddMessage(ctx, req.GetConversationId(), fromProtoRole(req.GetRole()), req.GetContent(), req.GetToolName())
|
|
if err != nil {
|
|
return nil, grpcerr.Internal(err)
|
|
}
|
|
return toProtoMessage(m), nil
|
|
}
|
|
|
|
func (s *Server) ListMessages(ctx context.Context, req *conversationv1.ListMessagesRequest) (*conversationv1.ListMessagesResponse, error) {
|
|
list, err := s.Svc.ListMessages(ctx, req.GetConversationId())
|
|
if err != nil {
|
|
return nil, grpcerr.Internal(err)
|
|
}
|
|
resp := &conversationv1.ListMessagesResponse{}
|
|
for _, m := range list {
|
|
resp.Messages = append(resp.Messages, toProtoMessage(m))
|
|
}
|
|
return resp, nil
|
|
}
|
|
|
|
func (s *Server) AddToolCall(ctx context.Context, req *conversationv1.AddToolCallRequest) (*conversationv1.AddToolCallResponse, error) {
|
|
err := s.Svc.AddToolCall(ctx, domain.ToolCall{
|
|
MessageID: req.GetMessageId(),
|
|
ToolName: req.GetToolName(),
|
|
ArgumentsJSON: req.GetArgumentsJson(),
|
|
Result: req.GetResult(),
|
|
IsError: req.GetIsError(),
|
|
})
|
|
if err != nil {
|
|
return nil, grpcerr.Internal(err)
|
|
}
|
|
return &conversationv1.AddToolCallResponse{}, nil
|
|
}
|