Skip to content

Commit

Permalink
generate endpoints to manage chat history
Browse files Browse the repository at this point in the history
  • Loading branch information
MahtabBukhari committed Dec 11, 2024
1 parent 0f7ee06 commit 4fa5bf6
Show file tree
Hide file tree
Showing 5 changed files with 188 additions and 0 deletions.
2 changes: 2 additions & 0 deletions db/config.go
Original file line number Diff line number Diff line change
Expand Up @@ -84,6 +84,8 @@ func InitDB() {
db.AutoMigrate(&WfRequest{})
db.AutoMigrate(&WfProcessingMap{})
db.AutoMigrate(&Tickets{})
db.AutoMigrate(&ChatMessage{})
db.AutoMigrate(&Chat{})

DB.MigrateTablesWithOrgUuid()
DB.MigrateOrganizationToWorkspace()
Expand Down
4 changes: 4 additions & 0 deletions db/interface.go
Original file line number Diff line number Diff line change
Expand Up @@ -201,4 +201,8 @@ type Database interface {
GetProductBrief(workspaceUuid string) (string, error)
GetFeatureBrief(featureUuid string) (string, error)
GetTicketsByPhaseUUID(featureUUID string, phaseUUID string) ([]Tickets, error)
AddChat(chat *Chat) (Chat, error)
GetChatByChatID(chatID string) (Chat, error)
AddChatMessage(message *ChatMessage) (ChatMessage, error)
GetChatMessagesForChatID(chatID string) ([]ChatMessage, error)
}
156 changes: 156 additions & 0 deletions handlers/chat.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,156 @@
package handlers

import (
"encoding/json"
"fmt"
"github.com/rs/xid"
"net/http"
"time"

"github.com/go-chi/chi"
"github.com/stakwork/sphinx-tribes/db"
)

type ChatHandler struct {
httpClient *http.Client
db db.Database
}

type ChatResponse struct {
Success bool `json:"success"`
Message string `json:"message"`
Data interface{} `json:"data,omitempty"`
}

type HistoryChatResponse struct {
Success bool `json:"success"`
Data interface{} `json:"data,omitempty"`
}

func NewChatHandler(httpClient *http.Client, database db.Database) *ChatHandler {
return &ChatHandler{
httpClient: httpClient,
db: database,
}
}

func (ch *ChatHandler) CreateChat(w http.ResponseWriter, r *http.Request) {
var request struct {
WorkspaceID string `json:"workspaceId"`
Title string `json:"title"`
}

if err := json.NewDecoder(r.Body).Decode(&request); err != nil {
w.WriteHeader(http.StatusBadRequest)
json.NewEncoder(w).Encode(ChatResponse{
Success: false,
Message: "Invalid request body",
})
return
}

chat := &db.Chat{
ID: xid.New().String(),
WorkspaceID: request.WorkspaceID,
Title: request.Title,
}

createdChat, err := ch.db.AddChat(chat)
if err != nil {
w.WriteHeader(http.StatusInternalServerError)
json.NewEncoder(w).Encode(ChatResponse{
Success: false,
Message: fmt.Sprintf("Failed to create chat: %v", err),
})
return
}

w.WriteHeader(http.StatusOK)
json.NewEncoder(w).Encode(ChatResponse{
Success: true,
Message: "Chat created successfully",
Data: createdChat,
})
}

func (ch *ChatHandler) SendMessage(w http.ResponseWriter, r *http.Request) {
var request struct {
ChatID string `json:"chatId"`
Message string `json:"message"`
ContextTags []struct {
Type string `json:"type"`
ID string `json:"id"`
} `json:"contextTags"`
}

if err := json.NewDecoder(r.Body).Decode(&request); err != nil {
w.WriteHeader(http.StatusBadRequest)
json.NewEncoder(w).Encode(ChatResponse{
Success: false,
Message: "Invalid request body",
})
return
}

message := &db.ChatMessage{
ID: xid.New().String(),
ChatID: request.ChatID,
Message: request.Message,
Role: "user",
Timestamp: time.Now(),
Status: "sending",
}

createdMessage, err := ch.db.AddChatMessage(message)
if err != nil {
w.WriteHeader(http.StatusInternalServerError)
json.NewEncoder(w).Encode(ChatResponse{
Success: false,
Message: fmt.Sprintf("Failed to send message: %v", err),
})
return
}

w.WriteHeader(http.StatusOK)
json.NewEncoder(w).Encode(ChatResponse{
Success: true,
Message: "Message sent successfully",
Data: createdMessage,
})
}

func (ch *ChatHandler) GetChatHistory(w http.ResponseWriter, r *http.Request) {
chatID := chi.URLParam(r, "uuid")
if chatID == "" {
w.WriteHeader(http.StatusBadRequest)
json.NewEncoder(w).Encode(ChatResponse{
Success: false,
Message: "Chat ID is required",
})
return
}

messages, err := ch.db.GetChatMessagesForChatID(chatID)
if err != nil {
w.WriteHeader(http.StatusInternalServerError)
json.NewEncoder(w).Encode(ChatResponse{
Success: false,
Message: fmt.Sprintf("Failed to fetch chat history: %v", err),
})
return
}

w.WriteHeader(http.StatusOK)
json.NewEncoder(w).Encode(HistoryChatResponse{
Success: true,
Data: messages,
})
}

func (ch *ChatHandler) ProcessChatResponse(w http.ResponseWriter, r *http.Request) {
w.WriteHeader(http.StatusOK)
json.NewEncoder(w).Encode(ChatResponse{
Success: true,
Message: "Stubbed out - process chat response",
})
}
25 changes: 25 additions & 0 deletions routes/chat.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
package routes

import (
"github.com/go-chi/chi"
"github.com/stakwork/sphinx-tribes/auth"
"github.com/stakwork/sphinx-tribes/db"
"github.com/stakwork/sphinx-tribes/handlers"
"net/http"
)

func ChatRoutes() chi.Router {
r := chi.NewRouter()
chatHandler := handlers.NewChatHandler(http.DefaultClient, db.DB)

r.Post("/response", chatHandler.ProcessChatResponse)

r.Group(func(r chi.Router) {
r.Use(auth.PubKeyContext)
r.Post("/", chatHandler.CreateChat)
r.Post("/send", chatHandler.SendMessage)
r.Get("/history/{uuid}", chatHandler.GetChatHistory)
})

return r
}
1 change: 1 addition & 0 deletions routes/index.go
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,7 @@ func NewRouter() *http.Server {
r.Mount("/features", FeatureRoutes())
r.Mount("/workflows", WorkflowRoutes())
r.Mount("/bounties/ticket", TicketRoutes())
r.Mount("/hivechat", ChatRoutes())

r.Group(func(r chi.Router) {
r.Get("/tribe_by_feed", tribeHandlers.GetFirstTribeByFeed)
Expand Down

0 comments on commit 4fa5bf6

Please sign in to comment.