summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorGrail Finder <wohilas@gmail.com>2025-11-21 16:48:44 +0300
committerGrail Finder <wohilas@gmail.com>2025-11-21 16:48:44 +0300
commit5fe03fa66c30f5d7ca6cdf9de1b1cfa2c38d6a45 (patch)
tree5b2f3a49b934eaadaf9bcce4454169ce00985579
parentbccbbe657e3aff084370b442efddeca7fbbf3e3e (diff)
Enha: rag loader
-rw-r--r--tables.go152
-rw-r--r--tui.go36
2 files changed, 115 insertions, 73 deletions
diff --git a/tables.go b/tables.go
index e87a905..6bb1e69 100644
--- a/tables.go
+++ b/tables.go
@@ -307,59 +307,105 @@ func makeRAGTable(fileList []string) *tview.Flex {
return ragflex
}
-// func makeLoadedRAGTable(fileList []string) *tview.Table {
-// actions := []string{"delete"}
-// rows, cols := len(fileList), len(actions)+1
-// fileTable := tview.NewTable().
-// SetBorders(true)
-// for r := 0; r < rows; r++ {
-// for c := 0; c < cols; c++ {
-// color := tcell.ColorWhite
-// if c < 1 {
-// fileTable.SetCell(r, c,
-// tview.NewTableCell(fileList[r]).
-// SetTextColor(color).
-// SetAlign(tview.AlignCenter))
-// } else {
-// fileTable.SetCell(r, c,
-// tview.NewTableCell(actions[c-1]).
-// SetTextColor(color).
-// SetAlign(tview.AlignCenter))
-// }
-// }
-// }
-// fileTable.Select(0, 0).SetFixed(1, 1).SetDoneFunc(func(key tcell.Key) {
-// if key == tcell.KeyEsc || key == tcell.KeyF1 {
-// pages.RemovePage(RAGPage)
-// return
-// }
-// if key == tcell.KeyEnter {
-// fileTable.SetSelectable(true, true)
-// }
-// }).SetSelectedFunc(func(row int, column int) {
-// defer pages.RemovePage(RAGPage)
-// tc := fileTable.GetCell(row, column)
-// tc.SetTextColor(tcell.ColorRed)
-// fileTable.SetSelectable(false, false)
-// fpath := fileList[row]
-// // notification := fmt.Sprintf("chat: %s; action: %s", fpath, tc.Text)
-// switch tc.Text {
-// case "delete":
-// if err := ragger.RemoveFile(fpath); err != nil {
-// logger.Error("failed to delete file", "filename", fpath, "error", err)
-// return
-// }
-// if err := notifyUser("chat deleted", fpath+" was deleted"); err != nil {
-// logger.Error("failed to send notification", "error", err)
-// }
-// return
-// default:
-// // pages.RemovePage(RAGPage)
-// return
-// }
-// })
-// return fileTable
-// }
+func makeLoadedRAGTable(fileList []string) *tview.Flex {
+ actions := []string{"delete"}
+ rows, cols := len(fileList), len(actions)+1
+ // Add 1 extra row for the "exit" option at the top
+ fileTable := tview.NewTable().
+ SetBorders(true)
+ longStatusView := tview.NewTextView()
+ longStatusView.SetText("Loaded RAG files list")
+ longStatusView.SetBorder(true).SetTitle("status")
+ longStatusView.SetChangedFunc(func() {
+ app.Draw()
+ })
+ ragflex := tview.NewFlex().SetDirection(tview.FlexRow).
+ AddItem(longStatusView, 0, 10, false).
+ AddItem(fileTable, 0, 60, true)
+
+ // Add the exit option as the first row (row 0)
+ fileTable.SetCell(0, 0,
+ tview.NewTableCell("Exit Loaded Files manager").
+ SetTextColor(tcell.ColorWhite).
+ SetAlign(tview.AlignCenter))
+ fileTable.SetCell(0, 1,
+ tview.NewTableCell("(Close without action)").
+ SetTextColor(tcell.ColorGray).
+ SetAlign(tview.AlignCenter))
+ fileTable.SetCell(0, 2,
+ tview.NewTableCell("exit").
+ SetTextColor(tcell.ColorGray).
+ SetAlign(tview.AlignCenter))
+
+ // Add the file rows starting from row 1
+ for r := 0; r < rows; r++ {
+ for c := 0; c < cols; c++ {
+ color := tcell.ColorWhite
+ if c < 1 {
+ fileTable.SetCell(r+1, c, // +1 to account for the exit row at index 0
+ tview.NewTableCell(fileList[r]).
+ SetTextColor(color).
+ SetAlign(tview.AlignCenter))
+ } else {
+ fileTable.SetCell(r+1, c, // +1 to account for the exit row at index 0
+ tview.NewTableCell(actions[c-1]).
+ SetTextColor(color).
+ SetAlign(tview.AlignCenter))
+ }
+ }
+ }
+
+ fileTable.Select(0, 0).SetFixed(1, 1).SetDoneFunc(func(key tcell.Key) {
+ if key == tcell.KeyEsc || key == tcell.KeyF1 || key == tcell.Key('x') || key == tcell.KeyCtrlX {
+ pages.RemovePage(RAGLoadedPage)
+ return
+ }
+ if key == tcell.KeyEnter {
+ fileTable.SetSelectable(true, true)
+ }
+ }).SetSelectedFunc(func(row int, column int) {
+ tc := fileTable.GetCell(row, column)
+ tc.SetTextColor(tcell.ColorRed)
+ fileTable.SetSelectable(false, false)
+
+ // Check if the selected row is the exit row (row 0) - do this first to avoid index issues
+ if row == 0 {
+ pages.RemovePage(RAGLoadedPage)
+ return
+ }
+
+ // For file rows, get the filename (row index - 1 because of the exit row at index 0)
+ fpath := fileList[row-1] // -1 to account for the exit row at index 0
+
+ switch tc.Text {
+ case "delete":
+ if err := ragger.RemoveFile(fpath); err != nil {
+ logger.Error("failed to delete file from RAG", "filename", fpath, "error", err)
+ longStatusView.SetText(fmt.Sprintf("Error deleting file: %v", err))
+ return
+ }
+ if err := notifyUser("RAG file deleted", fpath+" was deleted from RAG system"); err != nil {
+ logger.Error("failed to send notification", "error", err)
+ }
+ longStatusView.SetText(fpath + " was deleted from RAG system")
+ return
+ default:
+ pages.RemovePage(RAGLoadedPage)
+ return
+ }
+ })
+
+ // Add input capture to the flex container to handle 'x' key for closing
+ ragflex.SetInputCapture(func(event *tcell.EventKey) *tcell.EventKey {
+ if event.Key() == tcell.KeyRune && event.Rune() == 'x' {
+ pages.RemovePage(RAGLoadedPage)
+ return nil
+ }
+ return event
+ })
+
+ return ragflex
+}
func makeAgentTable(agentList []string) *tview.Table {
actions := []string{"filepath", "load"}
diff --git a/tui.go b/tui.go
index ced27b1..bce91a9 100644
--- a/tui.go
+++ b/tui.go
@@ -39,6 +39,7 @@ var (
helpPage = "helpPage"
renamePage = "renamePage"
RAGPage = "RAGPage"
+ RAGLoadedPage = "RAGLoadedPage"
propsPage = "propsPage"
codeBlockPage = "codeBlockPage"
imgPage = "imgPage"
@@ -75,6 +76,7 @@ var (
[yellow]Ctrl+j[white]: if chat agent is char.png will show the image; then any key to return
[yellow]Ctrl+a[white]: interrupt tts (needs tts server)
[yellow]Ctrl+g[white]: open RAG file manager (load files for context retrieval)
+[yellow]Ctrl+y[white]: list loaded RAG files (view and manage loaded files)
[yellow]Ctrl+q[white]: cycle through mentioned chars in chat, to pick persona to send next msg as
[yellow]Ctrl+x[white]: cycle through mentioned chars in chat, to pick persona to send next msg as (for llm)
RAG Window: [yellow]x[white]: close window | [yellow]Enter[white]: select action
@@ -823,26 +825,6 @@ func init() {
pages.AddPage(imgPage, imgView, true, true)
return nil
}
- // DEPRECATED: rag is deprecated until I change my mind
- // if event.Key() == tcell.KeyCtrlR && cfg.HFToken != "" {
- // // rag load
- // // menu of the text files from defined rag directory
- // files, err := os.ReadDir(cfg.RAGDir)
- // if err != nil {
- // logger.Error("failed to read dir", "dir", cfg.RAGDir, "error", err)
- // return nil
- // }
- // fileList := []string{}
- // for _, f := range files {
- // if f.IsDir() {
- // continue
- // }
- // fileList = append(fileList, f.Name())
- // }
- // chatRAGTable := makeRAGTable(fileList)
- // pages.AddPage(RAGPage, chatRAGTable, true, true)
- // return nil
- // }
if event.Key() == tcell.KeyCtrlR && cfg.STT_ENABLED {
defer updateStatusLine()
if asr.IsRecording() {
@@ -961,6 +943,20 @@ func init() {
pages.AddPage(RAGPage, chatRAGTable, true, true)
return nil
}
+ if event.Key() == tcell.KeyCtrlY { // Use Ctrl+Y to list loaded RAG files
+ // List files already loaded into the RAG system
+ fileList, err := ragger.ListLoaded()
+ if err != nil {
+ logger.Error("failed to list loaded RAG files", "error", err)
+ if notifyerr := notifyUser("failed to list RAG files", err.Error()); notifyerr != nil {
+ logger.Error("failed to send notification", "error", notifyerr)
+ }
+ return nil
+ }
+ chatLoadedRAGTable := makeLoadedRAGTable(fileList)
+ pages.AddPage(RAGLoadedPage, chatLoadedRAGTable, true, true)
+ return nil
+ }
// cannot send msg in editMode or botRespMode
if event.Key() == tcell.KeyEscape && !editMode && !botRespMode {
// read all text into buffer