diff --git a/.dockerignore b/.dockerignore new file mode 100644 index 0000000..8fce603 --- /dev/null +++ b/.dockerignore @@ -0,0 +1 @@ +data/ diff --git a/Chat.go b/Chat.go index 167e81f..9339cea 100644 --- a/Chat.go +++ b/Chat.go @@ -3,7 +3,6 @@ package main import ( "context" "encoding/json" - "fmt" "net/url" "sort" "strings" @@ -560,6 +559,7 @@ func GenerateModelPopoverHTML(refresh bool) string { } } FILTER .user = global currentUser AND .name != 'none' AND .to_delete = false + ORDER BY .position `, &llms) if err != nil { panic(err) @@ -614,7 +614,6 @@ func LoadSettingsHandler(c *fiber.Ctx) error { user.Email = url.QueryEscape(user.Email) stripeSubLink := "https://billing.stripe.com/p/login/test_eVa5kC1q7dogaaIcMM?prefilled_email=" + user.Email - fmt.Println(stripeSubLink) openaiExists, anthropicExists, mistralExists, groqExists, gooseaiExists, googleExists := getExistingKeys() diff --git a/LLM.go b/LLM.go index 9a0015c..3a458c1 100644 --- a/LLM.go +++ b/LLM.go @@ -62,10 +62,13 @@ func createLLM(c *fiber.Ctx) error { if modelID == "custom" { err := edgeClient.Execute(edgeCtx, ` + WITH + countLLM := count((SELECT LLM FILTER .user = global currentUser)) INSERT LLM { name := $0, context := $1, temperature := $2, + position := countLLM + 1, modelInfo := (INSERT ModelInfo { name := $0, modelID := $5, @@ -86,10 +89,13 @@ func createLLM(c *fiber.Ctx) error { } } else { err := edgeClient.Execute(edgeCtx, ` + WITH + countLLM := count((SELECT LLM FILTER .user = global currentUser)) INSERT LLM { name := $0, context := $1, temperature := $2, + position := countLLM + 1, modelInfo := (SELECT ModelInfo FILTER .modelID = $3 LIMIT 1), user := global currentUser } @@ -101,3 +107,35 @@ func createLLM(c *fiber.Ctx) error { return c.SendString(GenerateModelPopoverHTML(true)) } + +type PositionUpdate struct { + Position int `json:"position"` + ID string `json:"id"` +} + +func updateLLMPositionBatch(c *fiber.Ctx) error { + var positionUpdates []PositionUpdate + if err := c.BodyParser(&positionUpdates); err != nil { + return err + } + + for _, update := range positionUpdates { + idUUID, err := edgedb.ParseUUID(update.ID) + if err != nil { + panic(err) + } + + err = edgeClient.Execute(edgeCtx, ` + UPDATE LLM + FILTER .id = $0 AND .user = global currentUser + SET { + position := $1 + }; + `, idUUID, int32(update.Position)) + if err != nil { + panic(err) + } + } + + return nil +} diff --git a/dbschema/default.esdl b/dbschema/default.esdl index d9e08fc..bb4088a 100644 --- a/dbschema/default.esdl +++ b/dbschema/default.esdl @@ -86,6 +86,7 @@ module default { required name: str; required context: str; required temperature: float32; + required position: int32; required to_delete: bool { default := false; }; diff --git a/dbschema/migrations/00041-m1cmvjy.edgeql b/dbschema/migrations/00041-m1cmvjy.edgeql new file mode 100644 index 0000000..09f05cc --- /dev/null +++ b/dbschema/migrations/00041-m1cmvjy.edgeql @@ -0,0 +1,9 @@ +CREATE MIGRATION m1cmvjy3ikuh5ii6b7l7gckttjmqk554llocwqx7n4aibtzngybvoq + ONTO m1wlzna3nrrigx2urda3turnj6dcvcjgexeuxxqundupqet5jrkh7q +{ + ALTER TYPE default::LLM { + CREATE REQUIRED PROPERTY position: std::int32 { + SET REQUIRED USING ({0}); + }; + }; +}; diff --git a/main.go b/main.go index d1b4572..48111c8 100644 --- a/main.go +++ b/main.go @@ -89,6 +89,7 @@ func main() { app.Get("/loadUsageKPI", LoadUsageKPIHandler) app.Get("/loadKeys", LoadKeysHandler) app.Get("/loadSettings", LoadSettingsHandler) + app.Post("/updateLLMPositionBatch", updateLLMPositionBatch) // Authentication app.Get("/signin", handleUiSignIn) diff --git a/static/My logo - background (1).png b/static/My logo - background (1).png deleted file mode 100644 index 1c6b921..0000000 Binary files a/static/My logo - background (1).png and /dev/null differ diff --git a/static/icons/uncompress/anthropic.png b/static/icons/uncompress/anthropic.png deleted file mode 100644 index b238196..0000000 Binary files a/static/icons/uncompress/anthropic.png and /dev/null differ diff --git a/static/icons/uncompress/bouvai.png b/static/icons/uncompress/bouvai.png deleted file mode 100644 index 7e501ed..0000000 Binary files a/static/icons/uncompress/bouvai.png and /dev/null differ diff --git a/static/icons/uncompress/bouvai2.png b/static/icons/uncompress/bouvai2.png deleted file mode 100644 index 712acb1..0000000 Binary files a/static/icons/uncompress/bouvai2.png and /dev/null differ diff --git a/static/icons/uncompress/groq.png b/static/icons/uncompress/groq.png deleted file mode 100644 index 3156414..0000000 Binary files a/static/icons/uncompress/groq.png and /dev/null differ diff --git a/static/icons/uncompress/huggingface.png b/static/icons/uncompress/huggingface.png deleted file mode 100644 index 3412a5e..0000000 Binary files a/static/icons/uncompress/huggingface.png and /dev/null differ diff --git a/static/icons/uncompress/mistral.png b/static/icons/uncompress/mistral.png deleted file mode 100644 index a60df46..0000000 Binary files a/static/icons/uncompress/mistral.png and /dev/null differ diff --git a/static/icons/uncompress/openai.png b/static/icons/uncompress/openai.png deleted file mode 100644 index 77acf1b..0000000 Binary files a/static/icons/uncompress/openai.png and /dev/null differ diff --git a/static/model-selection-menu.js b/static/model-selection-menu.js new file mode 100644 index 0000000..c9fc759 --- /dev/null +++ b/static/model-selection-menu.js @@ -0,0 +1,54 @@ +let lastSelectedIndex = null; + +function toggleSelection(element) { + const elements = Array.from(document.getElementsByClassName('icon-text')); + const index = elements.indexOf(element); + + if (document.body.classList.contains('shift-pressed') && lastSelectedIndex !== null) { + const [start, end] = [lastSelectedIndex, index].sort((a, b) => a - b); + let allSelected = true; + for (let i = start; i <= end; i++) { + if (!elements[i].classList.contains('selected')) { + allSelected = false; + break; + } + } + for (let i = start; i <= end; i++) { + if (allSelected) { + elements[i].classList.remove('selected'); + elements[i].classList.add('unselected'); + } else { + elements[i].classList.add('selected'); + elements[i].classList.remove('unselected'); + } + } + lastSelectedIndex = null; + + const elements2 = Array.from(document.getElementsByClassName('icon-text')); + for (let i = 0; i < elements2.length; i++) { + elements2[i].classList.remove('shiftselected'); + } + } else if (document.body.classList.contains('shift-pressed') && lastSelectedIndex === null) { + lastSelectedIndex = index; + element.classList.toggle('shiftselected'); + } else { + element.classList.toggle('selected'); + element.classList.toggle('unselected'); + } + toggleSendButton(); +} + +function getSelectedModelsIDs() { + var selectedModelsIDs = []; + var selectedModels = document.getElementsByClassName('selected'); + for (var i = 0; i < selectedModels.length; i++) { + selectedModelsIDs.push(selectedModels[i].getAttribute('data-id')); + } + return selectedModelsIDs.length > 0 ? JSON.stringify(selectedModelsIDs) : '[]'; +} + +function toggleSendButton() { + var selectedModels = document.getElementsByClassName('selected'); + var sendButton = document.querySelector('button[disabled]'); + sendButton.disabled = selectedModels.length === 0; +} \ No newline at end of file diff --git a/views/layouts/main.html b/views/layouts/main.html index 58e4216..be81c7a 100644 --- a/views/layouts/main.html +++ b/views/layouts/main.html @@ -14,6 +14,8 @@ + + diff --git a/views/partials/popover-models.html b/views/partials/popover-models.html index 6cf2ece..9e49fc6 100644 --- a/views/partials/popover-models.html +++ b/views/partials/popover-models.html @@ -8,15 +8,17 @@