Cqn enter key
This commit is contained in:
parent
ed64fc01d8
commit
d2556a4a6d
59
Chat.go
59
Chat.go
@ -18,14 +18,14 @@ func ChatPageHandler(c *fiber.Ctx) error {
|
||||
edgeClient = edgeClient.WithGlobals(map[string]interface{}{"ext::auth::client_token": authCookie})
|
||||
}
|
||||
|
||||
fmt.Println("Current User: ", getCurrentUser())
|
||||
fmt.Println("Current User: ", getCurrentUser(), " - ", checkIfLogin())
|
||||
|
||||
return c.Render("chat", fiber.Map{"IsLogin": checkIfLogin()}, "layouts/main")
|
||||
return c.Render("chat", fiber.Map{"IsLogin": checkIfLogin(), "HaveKey": checkIfHaveKey()}, "layouts/main")
|
||||
}
|
||||
|
||||
func LoadModelSelectionHandler(c *fiber.Ctx) error {
|
||||
CheckedModels := []string{"gpt-3.5-turbo"} // Default model
|
||||
out, err := pongo2.Must(pongo2.FromFile("views/partials/modelsPopover.html")).Execute(pongo2.Context{
|
||||
out, err := pongo2.Must(pongo2.FromFile("views/partials/popover-models.html")).Execute(pongo2.Context{
|
||||
"CompanyInfos": CompanyInfos,
|
||||
"CheckedModels": CheckedModels,
|
||||
})
|
||||
@ -53,7 +53,7 @@ func LoadUsageKPIHandler(c *fiber.Ctx) error {
|
||||
log.Fatal(err)
|
||||
}
|
||||
|
||||
out, err := pongo2.Must(pongo2.FromFile("views/partials/usagePopover.html")).Execute(pongo2.Context{
|
||||
out, err := pongo2.Must(pongo2.FromFile("views/partials/popover-usage.html")).Execute(pongo2.Context{
|
||||
"TotalUsage": TotalUsage,
|
||||
})
|
||||
if err != nil {
|
||||
@ -64,6 +64,16 @@ func LoadUsageKPIHandler(c *fiber.Ctx) error {
|
||||
return c.SendString(out)
|
||||
}
|
||||
|
||||
func LoadSettingsHandler(c *fiber.Ctx) error {
|
||||
out, err := pongo2.Must(pongo2.FromFile("views/partials/popover-settings.html")).Execute(pongo2.Context{"IsLogin": checkIfLogin()})
|
||||
if err != nil {
|
||||
c.Status(fiber.StatusInternalServerError).JSON(fiber.Map{
|
||||
"error": "Error rendering template",
|
||||
})
|
||||
}
|
||||
return c.SendString(out)
|
||||
}
|
||||
|
||||
func DeleteMessageHandler(c *fiber.Ctx) error {
|
||||
messageId := c.FormValue("id")
|
||||
|
||||
@ -92,6 +102,9 @@ func DeleteMessageHandler(c *fiber.Ctx) error {
|
||||
|
||||
func LoadChatHandler(c *fiber.Ctx) error {
|
||||
if checkIfLogin() {
|
||||
if getCurrentUserKeys() == nil {
|
||||
return c.SendString(generateEnterKeyChatHTML())
|
||||
}
|
||||
return c.SendString(generateChatHTML())
|
||||
} else {
|
||||
return c.SendString(generateWelcomeChatHTML())
|
||||
@ -210,19 +223,53 @@ func GetMessageContentHandler(c *fiber.Ctx) error {
|
||||
}
|
||||
|
||||
func generateWelcomeChatHTML() string {
|
||||
welcomeMessage := `To start using JADE, please login.`
|
||||
|
||||
loginButton := `
|
||||
<a class="button is-primary is-small" href="/signin">
|
||||
Log in
|
||||
</a>`
|
||||
|
||||
htmlString := "<div class='columns is-centered' id='chat-container'><div class='column is-12-mobile is-8-tablet is-6-desktop' id='chat-messages'>"
|
||||
|
||||
NextMessages := []NextMessage{}
|
||||
nextMsg := NextMessage{
|
||||
Icon: "bouvai2", // Assuming Icon is a field you want to include from Message
|
||||
Content: markdownToHTML("Hi, I'm Bouvai. How can I help you today?"),
|
||||
Content: "<br>" + markdownToHTML(welcomeMessage) + loginButton,
|
||||
Hidden: false, // Assuming Hidden is a field you want to include from Message
|
||||
Id: "0",
|
||||
Name: "JADE",
|
||||
}
|
||||
NextMessages = append(NextMessages, nextMsg)
|
||||
|
||||
botOut, err := botTmpl.Execute(pongo2.Context{"Messages": NextMessages, "ConversationAreaId": 0})
|
||||
botOut, err := botTmpl.Execute(pongo2.Context{"Messages": NextMessages, "ConversationAreaId": 0, "NotClickable": !true})
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
htmlString += botOut
|
||||
htmlString += "<div style='height: 10px;'></div>"
|
||||
htmlString += "</div></div>"
|
||||
|
||||
// Render the HTML template with the messages
|
||||
return htmlString
|
||||
}
|
||||
|
||||
func generateEnterKeyChatHTML() string {
|
||||
welcomeMessage := `To start using JADE, please enter at least one key in the settings.`
|
||||
|
||||
htmlString := "<div class='columns is-centered' id='chat-container'><div class='column is-12-mobile is-8-tablet is-6-desktop' id='chat-messages'>"
|
||||
|
||||
NextMessages := []NextMessage{}
|
||||
nextMsg := NextMessage{
|
||||
Icon: "bouvai2", // Assuming Icon is a field you want to include from Message
|
||||
Content: "<br>" + markdownToHTML(welcomeMessage),
|
||||
Hidden: false, // Assuming Hidden is a field you want to include from Message
|
||||
Id: "0",
|
||||
Name: "JADE",
|
||||
}
|
||||
NextMessages = append(NextMessages, nextMsg)
|
||||
|
||||
botOut, err := botTmpl.Execute(pongo2.Context{"Messages": NextMessages, "ConversationAreaId": 0, "NotClickable": !true})
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
|
@ -8,6 +8,8 @@ import (
|
||||
"net/http"
|
||||
|
||||
"github.com/edgedb/edgedb-go"
|
||||
"github.com/flosch/pongo2"
|
||||
"github.com/gofiber/fiber/v2"
|
||||
)
|
||||
|
||||
type AnthropicChatCompletionRequest struct {
|
||||
@ -124,8 +126,69 @@ func EdgeMessages2AnthropicMessages(messages []Message) []AnthropicMessage {
|
||||
return AnthropicMessages
|
||||
}
|
||||
|
||||
func TestAnthropicKey(apiKey string) bool {
|
||||
url := "https://api.anthropic.com/v1/messages"
|
||||
|
||||
AnthropicMessages := []AnthropicMessage{
|
||||
{
|
||||
Role: "user",
|
||||
Content: "Hello",
|
||||
},
|
||||
}
|
||||
|
||||
requestBody := AnthropicChatCompletionRequest{
|
||||
Model: "claude-3-haiku-20240307",
|
||||
Messages: AnthropicMessages,
|
||||
MaxTokens: 10,
|
||||
Temperature: 0,
|
||||
}
|
||||
|
||||
jsonBody, err := json.Marshal(requestBody)
|
||||
if err != nil {
|
||||
return false
|
||||
}
|
||||
|
||||
req, err := http.NewRequest("POST", url, bytes.NewBuffer(jsonBody))
|
||||
if err != nil {
|
||||
return false
|
||||
}
|
||||
|
||||
req.Header.Set("content-Type", "application/json")
|
||||
req.Header.Set("anthropic-version", "2023-06-01")
|
||||
req.Header.Set("x-api-key", apiKey)
|
||||
|
||||
client := &http.Client{}
|
||||
resp, err := client.Do(req)
|
||||
if err != nil {
|
||||
return false
|
||||
}
|
||||
defer resp.Body.Close()
|
||||
|
||||
body, err := io.ReadAll(resp.Body)
|
||||
if err != nil {
|
||||
return false
|
||||
}
|
||||
|
||||
var chatCompletionResponse AnthropicChatCompletionResponse
|
||||
err = json.Unmarshal(body, &chatCompletionResponse)
|
||||
return err == nil
|
||||
}
|
||||
|
||||
func RequestAnthropic(model string, messages []Message, maxTokens int, temperature float64) (AnthropicChatCompletionResponse, error) {
|
||||
apiKey := "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" // TODO Use env variable
|
||||
var apiKey string
|
||||
err := edgeClient.QuerySingle(edgeCtx, `
|
||||
with
|
||||
filtered_keys := (
|
||||
select Key {
|
||||
key
|
||||
} filter .company = <str>$0
|
||||
)
|
||||
select filtered_keys.key limit 1
|
||||
`, &apiKey, "anthropic")
|
||||
if err != nil {
|
||||
return AnthropicChatCompletionResponse{}, fmt.Errorf("error getting OpenAI API key: %w", err)
|
||||
}
|
||||
|
||||
url := "https://api.anthropic.com/v1/messages"
|
||||
|
||||
AnthropicMessages := EdgeMessages2AnthropicMessages(messages)
|
||||
@ -181,3 +244,74 @@ func RequestAnthropic(model string, messages []Message, maxTokens int, temperatu
|
||||
|
||||
return chatCompletionResponse, nil
|
||||
}
|
||||
|
||||
func addAnthropicKey(c *fiber.Ctx) error {
|
||||
key := c.FormValue("key")
|
||||
|
||||
// Check if the key already exists
|
||||
err := edgeClient.QuerySingle(edgeCtx, `
|
||||
with
|
||||
filtered_keys := (
|
||||
select Key {
|
||||
key
|
||||
} filter .key = <str>$0 and .company = "anthropic"
|
||||
)
|
||||
select filtered_keys.key limit 1
|
||||
`, &key, key)
|
||||
if err == nil {
|
||||
return c.SendString("")
|
||||
}
|
||||
|
||||
if !TestAnthropicKey(key) {
|
||||
fmt.Println("Invalid Anthropic API Key")
|
||||
|
||||
NextMessages := []NextMessage{}
|
||||
nextMsg := NextMessage{
|
||||
Icon: "bouvai2", // Assuming Icon is a field you want to include from Message
|
||||
Content: "<br>" + markdownToHTML("Invalid Anthropic API Key"),
|
||||
Hidden: false, // Assuming Hidden is a field you want to include from Message
|
||||
Id: "0",
|
||||
Name: "JADE",
|
||||
}
|
||||
NextMessages = append(NextMessages, nextMsg)
|
||||
|
||||
botOut, err := botTmpl.Execute(pongo2.Context{"Messages": NextMessages, "ConversationAreaId": 0})
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
return c.SendString(botOut)
|
||||
}
|
||||
|
||||
err = edgeClient.Execute(edgeCtx, `
|
||||
UPDATE global currentUser.setting
|
||||
SET {
|
||||
keys += (
|
||||
INSERT Key {
|
||||
company := <str>$0,
|
||||
key := <str>$1,
|
||||
name := <str>$2,
|
||||
}
|
||||
)
|
||||
}`, "anthropic", key, "Anthropic API Key")
|
||||
if err != nil {
|
||||
fmt.Println("Error in edgedb.QuerySingle: in addOpenaiKey")
|
||||
fmt.Println(err)
|
||||
}
|
||||
|
||||
NextMessages := []NextMessage{}
|
||||
nextMsg := NextMessage{
|
||||
Icon: "bouvai2", // Assuming Icon is a field you want to include from Message
|
||||
Content: "<br>" + markdownToHTML("Key added successfully!"),
|
||||
Hidden: false, // Assuming Hidden is a field you want to include from Message
|
||||
Id: "0",
|
||||
Name: "JADE",
|
||||
}
|
||||
NextMessages = append(NextMessages, nextMsg)
|
||||
|
||||
botOut, err := botTmpl.Execute(pongo2.Context{"Messages": NextMessages, "ConversationAreaId": 0})
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
|
||||
return c.SendString(botOut)
|
||||
}
|
||||
|
172
RequestOpenai.go
172
RequestOpenai.go
@ -8,6 +8,8 @@ import (
|
||||
"net/http"
|
||||
|
||||
"github.com/edgedb/edgedb-go"
|
||||
"github.com/flosch/pongo2"
|
||||
"github.com/gofiber/fiber/v2"
|
||||
)
|
||||
|
||||
type OpenaiChatCompletionRequest struct {
|
||||
@ -115,8 +117,76 @@ func EdgeMessages2OpenaiMessages(messages []Message) []OpenaiMessage {
|
||||
return openaiMessages
|
||||
}
|
||||
|
||||
func TestOpenaiKey(apiKey string) bool {
|
||||
url := "https://api.openai.com/v1/chat/completions"
|
||||
|
||||
// Convert messages to OpenAI format
|
||||
openaiMessages := []OpenaiMessage{
|
||||
{
|
||||
Role: "user",
|
||||
Content: "Hello",
|
||||
},
|
||||
}
|
||||
|
||||
requestBody := OpenaiChatCompletionRequest{
|
||||
Model: "gpt-3.5-turbo",
|
||||
Messages: openaiMessages,
|
||||
Temperature: 0,
|
||||
}
|
||||
|
||||
jsonBody, err := json.Marshal(requestBody)
|
||||
if err != nil {
|
||||
return false
|
||||
}
|
||||
|
||||
req, err := http.NewRequest("POST", url, bytes.NewBuffer(jsonBody))
|
||||
if err != nil {
|
||||
return false
|
||||
}
|
||||
|
||||
req.Header.Set("Content-Type", "application/json")
|
||||
req.Header.Set("Authorization", "Bearer "+apiKey)
|
||||
|
||||
client := &http.Client{}
|
||||
resp, err := client.Do(req)
|
||||
if err != nil {
|
||||
return false
|
||||
}
|
||||
defer resp.Body.Close()
|
||||
|
||||
body, err := io.ReadAll(resp.Body)
|
||||
if err != nil {
|
||||
return false
|
||||
}
|
||||
|
||||
var chatCompletionResponse OpenaiChatCompletionResponse
|
||||
err = json.Unmarshal(body, &chatCompletionResponse)
|
||||
if err != nil {
|
||||
return false
|
||||
}
|
||||
if chatCompletionResponse.Choices == nil {
|
||||
return false
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
func RequestOpenai(model string, messages []Message, temperature float64) (OpenaiChatCompletionResponse, error) {
|
||||
apiKey := "sk-proj-f7StCvXCtcmiOOayiVmgT3BlbkFJlVtAcOo3JcrnGq1cPa5o" // TODO Use env variable
|
||||
var apiKey string
|
||||
err := edgeClient.QuerySingle(edgeCtx, `
|
||||
with
|
||||
filtered_keys := (
|
||||
select Key {
|
||||
key
|
||||
} filter .company = <str>$0
|
||||
)
|
||||
select filtered_keys.key limit 1
|
||||
`, &apiKey, "openai")
|
||||
if err != nil {
|
||||
return OpenaiChatCompletionResponse{}, fmt.Errorf("error getting OpenAI API key: %w", err)
|
||||
}
|
||||
|
||||
fmt.Println("OpenAI API key: ", apiKey)
|
||||
|
||||
url := "https://api.openai.com/v1/chat/completions"
|
||||
|
||||
// Convert messages to OpenAI format
|
||||
@ -171,3 +241,103 @@ func RequestOpenai(model string, messages []Message, temperature float64) (Opena
|
||||
|
||||
return chatCompletionResponse, nil
|
||||
}
|
||||
|
||||
func addOpenaiKey(c *fiber.Ctx) error {
|
||||
key := c.FormValue("key")
|
||||
|
||||
// Check if the key already exists
|
||||
var keyUUID edgedb.UUID
|
||||
err := edgeClient.QuerySingle(edgeCtx, `
|
||||
with
|
||||
filtered_keys := (
|
||||
select Key {
|
||||
id
|
||||
} filter .key = <str>$0 and .company = "openai"
|
||||
)
|
||||
select filtered_keys.key limit 1
|
||||
`, &keyUUID, key)
|
||||
if err == nil {
|
||||
fmt.Println("Error in edgedb.Query: in addOpenaiKey")
|
||||
return c.SendString("")
|
||||
}
|
||||
|
||||
if !TestOpenaiKey(key) {
|
||||
fmt.Println("Invalid OpenAI API Key")
|
||||
NextMessages := []NextMessage{}
|
||||
nextMsg := NextMessage{
|
||||
Icon: "bouvai2", // Assuming Icon is a field you want to include from Message
|
||||
Content: "<br>" + markdownToHTML("Invalid OpenAI API Key"),
|
||||
Hidden: false, // Assuming Hidden is a field you want to include from Message
|
||||
Id: "0",
|
||||
Name: "JADE",
|
||||
}
|
||||
NextMessages = append(NextMessages, nextMsg)
|
||||
|
||||
botOut, err := botTmpl.Execute(pongo2.Context{"Messages": NextMessages, "ConversationAreaId": 0})
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
return c.SendString(botOut)
|
||||
}
|
||||
|
||||
// Check if the company key already exists
|
||||
err = edgeClient.QuerySingle(edgeCtx, `
|
||||
with
|
||||
filtered_keys := (
|
||||
select Key {
|
||||
id
|
||||
} filter .company = "openai"
|
||||
)
|
||||
select filtered_keys.key limit 1
|
||||
`, &keyUUID, key)
|
||||
if err != nil {
|
||||
fmt.Println("Company key already exists")
|
||||
err = edgeClient.Execute(edgeCtx, `
|
||||
UPDATE Key filter .company = <str>$0 AND .key = <str>$1
|
||||
SET {
|
||||
key := <str>$1,
|
||||
}
|
||||
`, "openai", key)
|
||||
if err != nil {
|
||||
fmt.Println("Error in edgedb.QuerySingle: in addOpenaiKey")
|
||||
fmt.Println(err)
|
||||
}
|
||||
|
||||
return c.SendString("")
|
||||
}
|
||||
|
||||
fmt.Println("OpenAI API key: ", key)
|
||||
|
||||
err = edgeClient.Execute(edgeCtx, `
|
||||
UPDATE global currentUser.setting
|
||||
SET {
|
||||
keys += (
|
||||
INSERT Key {
|
||||
company := <str>$0,
|
||||
key := <str>$1,
|
||||
name := <str>$2,
|
||||
}
|
||||
)
|
||||
}`, "openai", key, "OpenAI API Key")
|
||||
if err != nil {
|
||||
fmt.Println("Error in edgedb.QuerySingle: in addOpenaiKey")
|
||||
fmt.Println(err)
|
||||
}
|
||||
|
||||
NextMessages := []NextMessage{}
|
||||
nextMsg := NextMessage{
|
||||
Icon: "bouvai2", // Assuming Icon is a field you want to include from Message
|
||||
Content: "<br> Key added successfully!",
|
||||
Hidden: false, // Assuming Hidden is a field you want to include from Message
|
||||
Id: "0",
|
||||
Name: "JADE",
|
||||
}
|
||||
NextMessages = append(NextMessages, nextMsg)
|
||||
|
||||
botOut, err := botTmpl.Execute(pongo2.Context{"Messages": NextMessages, "ConversationAreaId": 0})
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
|
||||
return c.SendString(botOut)
|
||||
}
|
||||
|
85
database.go
85
database.go
@ -13,19 +13,16 @@ var edgeCtx context.Context
|
||||
var edgeClient *edgedb.Client
|
||||
|
||||
type User struct {
|
||||
ID edgedb.UUID `edgedb:"id"`
|
||||
Email string `edgedb:"email"`
|
||||
Name string `edgedb:"name"`
|
||||
Setting Setting `edgedb:"setting"`
|
||||
Conversations []Conversation `edgedb:"conversations"`
|
||||
Usages []Usage `edgedb:"usages"`
|
||||
ID edgedb.UUID `edgedb:"id"`
|
||||
Setting Setting `edgedb:"setting"`
|
||||
}
|
||||
|
||||
type Key struct {
|
||||
ID edgedb.UUID `edgedb:"id"`
|
||||
Name string `edgedb:"name"`
|
||||
Key string `edgedb:"key"`
|
||||
Date time.Time `edgedb:"date"`
|
||||
ID edgedb.UUID `edgedb:"id"`
|
||||
Name string `edgedb:"name"`
|
||||
Company string `edgedb:"company"`
|
||||
Key string `edgedb:"key"`
|
||||
Date time.Time `edgedb:"date"`
|
||||
}
|
||||
|
||||
type Setting struct {
|
||||
@ -35,24 +32,27 @@ type Setting struct {
|
||||
}
|
||||
|
||||
type Conversation struct {
|
||||
ID edgedb.UUID `edgedb:"id"`
|
||||
Name string `edgedb:"name"`
|
||||
Areas []Area `edgedb:"areas"`
|
||||
ID edgedb.UUID `edgedb:"id"`
|
||||
Name string `edgedb:"name"`
|
||||
Date time.Time `edgedb:"date"`
|
||||
User User `edgedb:"user"`
|
||||
}
|
||||
|
||||
type Area struct {
|
||||
ID edgedb.UUID `edgedb:"id"`
|
||||
Position int `edgedb:"position"`
|
||||
Messages []Message `edgedb:"messages"`
|
||||
ID edgedb.UUID `edgedb:"id"`
|
||||
Position int `edgedb:"position"`
|
||||
Conv Conversation `edgedb:"conversation"`
|
||||
}
|
||||
|
||||
type Message struct {
|
||||
ID edgedb.UUID `edgedb:"id"`
|
||||
Content string `edgedb:"content"`
|
||||
Role string `edgedb:"role"`
|
||||
ModelID edgedb.OptionalStr `edgedb:"model_id"`
|
||||
Selected edgedb.OptionalBool `edgedb:"selected"`
|
||||
Role string `edgedb:"role"`
|
||||
Content string `edgedb:"content"`
|
||||
Date time.Time `edgedb:"date"`
|
||||
Area Area `edgedb:"area"`
|
||||
Conv Conversation `edgedb:"conversation"`
|
||||
}
|
||||
|
||||
type Usage struct {
|
||||
@ -109,10 +109,34 @@ func checkIfLogin() bool {
|
||||
return err == nil
|
||||
}
|
||||
|
||||
func insertArea() edgedb.UUID {
|
||||
// Insert a new area.
|
||||
func insertNewConversation() edgedb.UUID {
|
||||
var inserted struct{ id edgedb.UUID }
|
||||
err := edgeClient.QuerySingle(edgeCtx, `
|
||||
INSERT Conversation {
|
||||
name := 'Default',
|
||||
user := global currentUser
|
||||
}
|
||||
`, &inserted)
|
||||
if err != nil {
|
||||
fmt.Println("Error in edgedb.QuerySingle: in insertNewConversation")
|
||||
log.Fatal(err)
|
||||
}
|
||||
return inserted.id
|
||||
}
|
||||
|
||||
func insertArea() edgedb.UUID {
|
||||
// If the Default conversation doesn't exist, create it.
|
||||
err := edgeClient.QuerySingle(edgeCtx, `
|
||||
SELECT Conversation
|
||||
FILTER .name = 'Default' AND .user = global currentUser
|
||||
LIMIT 1
|
||||
`, nil)
|
||||
if err != nil {
|
||||
insertNewConversation()
|
||||
}
|
||||
// Insert a new area.
|
||||
var inserted struct{ id edgedb.UUID }
|
||||
err = edgeClient.QuerySingle(edgeCtx, `
|
||||
WITH
|
||||
positionVar := count((SELECT Area FILTER .conversation.name = 'Default' AND .conversation.user = global currentUser)) + 1
|
||||
INSERT Area {
|
||||
@ -168,10 +192,10 @@ func insertBotMessage(content string, selected bool, model string) edgedb.UUID {
|
||||
content := <str>$2,
|
||||
selected := <bool>$3,
|
||||
conversation := (
|
||||
SELECT Conversation
|
||||
FILTER .name = 'Default' AND .user = global currentUser
|
||||
SELECT Area
|
||||
FILTER .id = <uuid>$4
|
||||
LIMIT 1
|
||||
),
|
||||
).conversation,
|
||||
area := (
|
||||
SELECT Area
|
||||
FILTER .id = <uuid>$4
|
||||
@ -212,3 +236,18 @@ func getAllMessages() []Message {
|
||||
|
||||
return messages
|
||||
}
|
||||
|
||||
func getCurrentUserKeys() []Key {
|
||||
var result []Key
|
||||
err := edgeClient.Query(edgeCtx, "SELECT global currentUser.setting.keys", &result)
|
||||
if err != nil {
|
||||
fmt.Println("Error in edgedb.Query: in getCurrentUserKeys")
|
||||
fmt.Println(err)
|
||||
}
|
||||
return result
|
||||
}
|
||||
|
||||
func checkIfHaveKey() bool {
|
||||
keys := getCurrentUserKeys()
|
||||
return keys != nil && len(keys) > 0
|
||||
}
|
||||
|
5
main.go
5
main.go
@ -40,9 +40,14 @@ func main() {
|
||||
app.Get("/generateMultipleMessages", GenerateMultipleMessages)
|
||||
app.Get("/messageContent", GetMessageContentHandler)
|
||||
|
||||
// Settings routes
|
||||
app.Post("/addOpenaiKey", addOpenaiKey)
|
||||
app.Post("/addAnthropicKey", addAnthropicKey)
|
||||
|
||||
// Popovers
|
||||
app.Get("/loadModelSelection", LoadModelSelectionHandler)
|
||||
app.Get("/loadUsageKPI", LoadUsageKPIHandler)
|
||||
app.Get("/loadSettings", LoadSettingsHandler)
|
||||
|
||||
// Authentication
|
||||
app.Get("/signin", handleUiSignIn)
|
||||
|
@ -1,14 +1,18 @@
|
||||
<div class="chat-container mt-5">
|
||||
|
||||
<hx hx-get="/loadChat" hx-trigger="load" hx-swap="outerHTML"></hx>
|
||||
<hx hx-get="/loadChat" hx-trigger="load once" hx-swap="outerHTML"></hx>
|
||||
|
||||
|
||||
<div class="chat-input-container mb-5">
|
||||
<div class="textarea-wrapper">
|
||||
<textarea class="textarea" placeholder="Type your message here..." name="message"></textarea>
|
||||
<textarea {% if not IsLogin or not HaveKey %}disabled{% endif %} class="textarea"
|
||||
placeholder="Type your message here..." name="message"></textarea>
|
||||
<div class="button-group">
|
||||
<hx hx-get="/loadModelSelection" hx-trigger="load" hx-swap="outerHTML" hx-target="this"></hx>
|
||||
<hx hx-get="/loadSettings" hx-trigger="load" hx-swap="outerHTML" hx-target="this"></hx>
|
||||
<hx hx-get="/loadUsageKPI" hx-trigger="load" hx-swap="outerHTML" hx-target="this"></hx>
|
||||
<button type="submit" class="send-button button is-primary is-small" hx-post="/requestMultipleMessages"
|
||||
<hx hx-get="/loadModelSelection" hx-trigger="load" hx-swap="outerHTML" hx-target="this"></hx>
|
||||
<button {% if not IsLogin or not HaveKey %}disabled{% endif %} type="submit"
|
||||
class="send-button button is-primary is-small" hx-post="/requestMultipleMessages"
|
||||
hx-swap="beforeend settle:200ms" hx-target="#chat-messages" id="chat-input-send-btn"
|
||||
class="chat-input" hx-include="[name='message'], [name^='model-check-']">Send</button>
|
||||
</div>
|
||||
|
@ -4,8 +4,8 @@
|
||||
<div class='rows'>
|
||||
{% for message in Messages %}
|
||||
<div class='row is-full mt-1'>
|
||||
<a href="#" hx-get="/messageContent?id={{ message.Id }}" class="is-clickable"
|
||||
hx-target="#content-{{ ConversationAreaId }}" onclick="toggleGrayscale(this)">
|
||||
<a {% if NotClickable %} href="#" hx-get="/messageContent?id={{ message.Id }}" class="is-clickable"
|
||||
onclick="toggleGrayscale(this)" hx-target="#content-{{ ConversationAreaId }}" {% endif %}>
|
||||
<figure class="image is-48x48" style="flex-shrink: 0;">
|
||||
<img src="icons/{{ message.Icon }}.png" alt="User Image" {% if message.Hidden %}
|
||||
style="filter: grayscale(100%);" {% endif %} title="{{ message.Name }}">
|
||||
|
@ -13,13 +13,9 @@
|
||||
<div class="navbar-item">
|
||||
<div class="buttons">
|
||||
{% if IsLogin %}
|
||||
<a class="button is-light is-small" href="/signout">
|
||||
<a class="button is-small is-info is-outlined" href="/signout">
|
||||
Log out
|
||||
</a>
|
||||
{% else %}
|
||||
<a class="button is-light is-small" href="/signin">
|
||||
Log in
|
||||
</a>
|
||||
{% endif %}
|
||||
</div>
|
||||
</div>
|
||||
|
42
views/partials/popover-settings.html
Normal file
42
views/partials/popover-settings.html
Normal file
@ -0,0 +1,42 @@
|
||||
<div class="dropdown is-hoverable is-up">
|
||||
<div class="dropdown-trigger">
|
||||
<button class="button is-small" aria-haspopup="true" aria-controls="dropdown-menu4">
|
||||
<span>Settings</span>
|
||||
</button>
|
||||
</div>
|
||||
<div class="dropdown-menu" id="dropdown-menu4" role="menu">
|
||||
<div class="dropdown-content">
|
||||
<div class="dropdown-item">
|
||||
<div class="field">
|
||||
<form id="api-keys-form" method="post" action="/addKeys" hx-trigger="submit"
|
||||
hx-target="#chat-messages" hx-swap="beforeend">
|
||||
<div class="field has-addons">
|
||||
<p class="control has-icons-left is-expanded">
|
||||
<input class="input is-small" type="text" placeholder="OpenAI API key" name="openai_key"
|
||||
autocomplete="off" {% if not IsLogin %}disabled{% endif %}>
|
||||
<span class="icon is-small is-left">
|
||||
<i class="fas fa-lock"></i>
|
||||
</span>
|
||||
</p>
|
||||
</div>
|
||||
<div class="field has-addons">
|
||||
<p class="control has-icons-left is-expanded">
|
||||
<input class="input is-small" type="text" placeholder="Anthropic API key"
|
||||
name="anthropic_key" autocomplete="off" {% if not IsLogin %}disabled{% endif %}>
|
||||
<span class="icon is-small is-left">
|
||||
<i class="fas fa-lock"></i>
|
||||
</span>
|
||||
</p>
|
||||
</div>
|
||||
<div class="field has-addons">
|
||||
<p class="control">
|
||||
<button {% if not IsLogin %}disabled{% endif %} type="submit"
|
||||
class="button is-small">Submit</button>
|
||||
</p>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
Loading…
x
Reference in New Issue
Block a user