summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--.gitignore1
-rw-r--r--session.go19
-rw-r--r--tables.go76
-rw-r--r--tui.go28
4 files changed, 120 insertions, 4 deletions
diff --git a/.gitignore b/.gitignore
index 253db67..b980d4e 100644
--- a/.gitignore
+++ b/.gitignore
@@ -9,3 +9,4 @@ sysprompts/*
!sysprompts/cluedo.json
history_bak/
.aider*
+tags
diff --git a/session.go b/session.go
index 7d790f3..8ffabc2 100644
--- a/session.go
+++ b/session.go
@@ -7,6 +7,7 @@ import (
"fmt"
"os"
"os/exec"
+ "path/filepath"
"strings"
"time"
)
@@ -34,6 +35,24 @@ func exportChat() error {
return os.WriteFile(activeChatName+".json", data, 0666)
}
+func importChat(filename string) error {
+ data, err := os.ReadFile(filename)
+ if err != nil {
+ return err
+ }
+ messages := []models.RoleMsg{}
+ if err := json.Unmarshal(data, &messages); err != nil {
+ return err
+ }
+ activeChatName = filepath.Base(filename)
+ chatBody.Messages = messages
+ cfg.AssistantRole = messages[1].Role
+ if cfg.AssistantRole == cfg.UserRole {
+ cfg.AssistantRole = messages[2].Role
+ }
+ return nil
+}
+
func updateStorageChat(name string, msgs []models.RoleMsg) error {
var err error
chat, ok := chatMap[name]
diff --git a/tables.go b/tables.go
index b80e088..bd85356 100644
--- a/tables.go
+++ b/tables.go
@@ -457,3 +457,79 @@ func makeCodeBlockTable(codeBlocks []string) *tview.Table {
})
return table
}
+
+func makeImportChatTable(filenames []string) *tview.Table {
+ actions := []string{"load"}
+ rows, cols := len(filenames), len(actions)+1
+ chatActTable := tview.NewTable().
+ SetBorders(true)
+ for r := 0; r < rows; r++ {
+ for c := 0; c < cols; c++ {
+ color := tcell.ColorWhite
+ if c < 1 {
+ chatActTable.SetCell(r, c,
+ tview.NewTableCell(filenames[r]).
+ SetTextColor(color).
+ SetAlign(tview.AlignCenter))
+ } else {
+ chatActTable.SetCell(r, c,
+ tview.NewTableCell(actions[c-1]).
+ SetTextColor(color).
+ SetAlign(tview.AlignCenter))
+ }
+ }
+ }
+ chatActTable.Select(0, 0).SetFixed(1, 1).SetDoneFunc(func(key tcell.Key) {
+ if key == tcell.KeyEsc || key == tcell.KeyF1 {
+ pages.RemovePage(historyPage)
+ return
+ }
+ if key == tcell.KeyEnter {
+ chatActTable.SetSelectable(true, true)
+ }
+ }).SetSelectedFunc(func(row int, column int) {
+ tc := chatActTable.GetCell(row, column)
+ tc.SetTextColor(tcell.ColorRed)
+ chatActTable.SetSelectable(false, false)
+ selected := filenames[row]
+ // notification := fmt.Sprintf("chat: %s; action: %s", selectedChat, tc.Text)
+ switch tc.Text {
+ case "load":
+ if err := importChat(selected); err != nil {
+ logger.Warn("failed to import chat", "filename", selected)
+ pages.RemovePage(historyPage)
+ return
+ }
+ colorText()
+ updateStatusLine()
+ // redraw the text in text area
+ textView.SetText(chatToText(cfg.ShowSys))
+ pages.RemovePage(historyPage)
+ app.SetFocus(textArea)
+ return
+ case "rename":
+ pages.RemovePage(historyPage)
+ pages.AddPage(renamePage, renameWindow, true, true)
+ return
+ case "delete":
+ sc, ok := chatMap[selected]
+ if !ok {
+ // no chat found
+ pages.RemovePage(historyPage)
+ return
+ }
+ if err := store.RemoveChat(sc.ID); err != nil {
+ logger.Error("failed to remove chat from db", "chat_id", sc.ID, "chat_name", sc.Name)
+ }
+ if err := notifyUser("chat deleted", selected+" was deleted"); err != nil {
+ logger.Error("failed to send notification", "error", err)
+ }
+ pages.RemovePage(historyPage)
+ return
+ default:
+ pages.RemovePage(historyPage)
+ return
+ }
+ })
+ return chatActTable
+}
diff --git a/tui.go b/tui.go
index 91c042a..ce9c6a5 100644
--- a/tui.go
+++ b/tui.go
@@ -8,6 +8,7 @@ import (
_ "image/jpeg"
_ "image/png"
"os"
+ "path"
"slices"
"strconv"
"strings"
@@ -54,7 +55,7 @@ var (
[yellow]F8[white]: copy n msg to clipboard (linux xclip)
[yellow]F9[white]: table to copy from; with all code blocks
[yellow]F10[white]: manage loaded rag files (that already in vector db)
-[yellow]F11[white]: switch RAGEnabled boolean
+[yellow]F11[white]: import chat file
[yellow]F12[white]: show this help page
[yellow]Ctrl+w[white]: resume generation on the last msg
[yellow]Ctrl+s[white]: load new char/agent
@@ -201,7 +202,9 @@ func makePropsForm(props map[string]float32) *tview.Form {
AddTextView("Notes", "Props for llamacpp completion call", 40, 2, true, false).
AddCheckbox("Insert <think> (/completion only)", cfg.ThinkUse, func(checked bool) {
cfg.ThinkUse = checked
- }).AddDropDown("Set log level (Enter): ", []string{"Debug", "Info", "Warn"}, 1,
+ }).AddCheckbox("RAG use", cfg.RAGEnabled, func(checked bool) {
+ cfg.RAGEnabled = checked
+ }).AddDropDown("Set log level (Enter): ", []string{"Debug", "Info", "Warn"}, 1,
func(option string, optionIndex int) {
setLogLevel(option)
}).AddDropDown("Select an api: ", slices.Insert(cfg.ApiLinks, 0, cfg.CurrentAPI), 0,
@@ -555,8 +558,25 @@ func init() {
return nil
}
if event.Key() == tcell.KeyF11 {
- // xor
- cfg.RAGEnabled = !cfg.RAGEnabled
+ // read files in chat_exports
+ dirname := "chat_exports"
+ filelist, err := os.ReadDir(dirname)
+ if err != nil {
+ if err := notifyUser("failed to load exports", err.Error()); err != nil {
+ logger.Error("failed to send notification", "error", err)
+ }
+ }
+ fli := []string{}
+ for _, f := range filelist {
+ if f.IsDir() || !strings.HasSuffix(f.Name(), ".json") {
+ continue
+ }
+ fpath := path.Join(dirname, f.Name())
+ fli = append(fli, fpath)
+ }
+ // check error
+ exportsTable := makeImportChatTable(fli)
+ pages.AddPage(historyPage, exportsTable, true, true)
updateStatusLine()
return nil
}