Enha: codingdir for coding assistant
This commit is contained in:
@@ -43,6 +43,7 @@ STT_SR = 16000 # Sample rate for audio recording
|
|||||||
DBPATH = "gflt.db"
|
DBPATH = "gflt.db"
|
||||||
FilePickerDir = "." # Directory where file picker should start
|
FilePickerDir = "." # Directory where file picker should start
|
||||||
FilePickerExts = "png,jpg,jpeg,gif,webp" # Comma-separated list of allowed file extensions for file picker
|
FilePickerExts = "png,jpg,jpeg,gif,webp" # Comma-separated list of allowed file extensions for file picker
|
||||||
|
CodingDir = "." # Default directory for coding assistant file operations (relative paths resolved against this)
|
||||||
EnableMouse = false # Enable mouse support in the UI
|
EnableMouse = false # Enable mouse support in the UI
|
||||||
# character specific context
|
# character specific context
|
||||||
CharSpecificContextEnabled = true
|
CharSpecificContextEnabled = true
|
||||||
|
|||||||
@@ -31,6 +31,7 @@ type Config struct {
|
|||||||
DBPATH string `toml:"DBPATH"`
|
DBPATH string `toml:"DBPATH"`
|
||||||
FilePickerDir string `toml:"FilePickerDir"`
|
FilePickerDir string `toml:"FilePickerDir"`
|
||||||
FilePickerExts string `toml:"FilePickerExts"`
|
FilePickerExts string `toml:"FilePickerExts"`
|
||||||
|
CodingDir string `toml:"CodingDir"`
|
||||||
ImagePreview bool `toml:"ImagePreview"`
|
ImagePreview bool `toml:"ImagePreview"`
|
||||||
EnableMouse bool `toml:"EnableMouse"`
|
EnableMouse bool `toml:"EnableMouse"`
|
||||||
// embeddings
|
// embeddings
|
||||||
|
|||||||
@@ -145,6 +145,9 @@ This document explains how to set up and configure the application using the `co
|
|||||||
#### FilePickerExts (`"png,jpg,jpeg,gif,webp"`)
|
#### FilePickerExts (`"png,jpg,jpeg,gif,webp"`)
|
||||||
- Comma-separated list of allowed file extensions for the file picker.
|
- Comma-separated list of allowed file extensions for the file picker.
|
||||||
|
|
||||||
|
#### CodingDir (`"."`)
|
||||||
|
- Default directory for coding assistant file operations. Relative paths in file tools (file_read, file_write, etc.) are resolved against this directory. Use absolute paths (starting with `/`) to bypass this.
|
||||||
|
|
||||||
#### EnableMouse (`false`)
|
#### EnableMouse (`false`)
|
||||||
- Enable or disable mouse support in the UI. When set to `true`, allows clicking buttons and interacting with UI elements using the mouse, but prevents the terminal from handling mouse events normally (such as selecting and copying text). When set to `false`, enables default terminal behavior allowing you to select and copy text, but disables mouse interaction with UI elements.
|
- Enable or disable mouse support in the UI. When set to `true`, allows clicking buttons and interacting with UI elements using the mouse, but prevents the terminal from handling mouse events normally (such as selecting and copying text). When set to `false`, enables default terminal behavior allowing you to select and copy text, but disables mouse interaction with UI elements.
|
||||||
|
|
||||||
|
|||||||
File diff suppressed because one or more lines are too long
33
tables.go
33
tables.go
@@ -820,7 +820,7 @@ func makeFilePicker() *tview.Flex {
|
|||||||
}
|
}
|
||||||
// Create UI elements
|
// Create UI elements
|
||||||
listView := tview.NewList()
|
listView := tview.NewList()
|
||||||
listView.SetBorder(true).SetTitle("Files & Directories").SetTitleAlign(tview.AlignLeft)
|
listView.SetBorder(true).SetTitle("Files & Directories [c: set CodingDir]").SetTitleAlign(tview.AlignLeft)
|
||||||
// Status view for selected file information
|
// Status view for selected file information
|
||||||
statusView := tview.NewTextView()
|
statusView := tview.NewTextView()
|
||||||
statusView.SetBorder(true).SetTitle("Selected File").SetTitleAlign(tview.AlignLeft)
|
statusView.SetBorder(true).SetTitle("Selected File").SetTitleAlign(tview.AlignLeft)
|
||||||
@@ -1032,6 +1032,37 @@ func makeFilePicker() *tview.Flex {
|
|||||||
refreshList(currentDisplayDir, "")
|
refreshList(currentDisplayDir, "")
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
if event.Rune() == 'c' {
|
||||||
|
// Set CodingDir to current directory
|
||||||
|
itemIndex := listView.GetCurrentItem()
|
||||||
|
if itemIndex >= 0 && itemIndex < listView.GetItemCount() {
|
||||||
|
itemText, _ := listView.GetItemText(itemIndex)
|
||||||
|
// Get the actual directory path
|
||||||
|
var targetDir string
|
||||||
|
if strings.HasPrefix(itemText, "Exit") || strings.HasPrefix(itemText, "Select this directory") {
|
||||||
|
targetDir = currentDisplayDir
|
||||||
|
} else {
|
||||||
|
actualItemName := itemText
|
||||||
|
if bracketPos := strings.Index(itemText, " ["); bracketPos != -1 {
|
||||||
|
actualItemName = itemText[:bracketPos]
|
||||||
|
}
|
||||||
|
if strings.HasPrefix(actualItemName, "../") {
|
||||||
|
targetDir = path.Dir(currentDisplayDir)
|
||||||
|
} else if strings.HasSuffix(actualItemName, "/") {
|
||||||
|
dirName := strings.TrimSuffix(actualItemName, "/")
|
||||||
|
targetDir = path.Join(currentDisplayDir, dirName)
|
||||||
|
} else {
|
||||||
|
targetDir = currentDisplayDir
|
||||||
|
}
|
||||||
|
}
|
||||||
|
cfg.CodingDir = targetDir
|
||||||
|
if err := notifyUser("CodingDir", "Set to: "+targetDir); err != nil {
|
||||||
|
logger.Error("failed to notify user", "error", err)
|
||||||
|
}
|
||||||
|
pages.RemovePage(filePickerPage)
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
}
|
||||||
case tcell.KeyEnter:
|
case tcell.KeyEnter:
|
||||||
// Get the currently highlighted item in the list
|
// Get the currently highlighted item in the list
|
||||||
itemIndex := listView.GetCurrentItem()
|
itemIndex := listView.GetCurrentItem()
|
||||||
|
|||||||
22
tools.go
22
tools.go
@@ -9,6 +9,7 @@ import (
|
|||||||
"io"
|
"io"
|
||||||
"os"
|
"os"
|
||||||
"os/exec"
|
"os/exec"
|
||||||
|
"path/filepath"
|
||||||
"regexp"
|
"regexp"
|
||||||
"strconv"
|
"strconv"
|
||||||
"strings"
|
"strings"
|
||||||
@@ -377,6 +378,8 @@ func fileCreate(args map[string]string) []byte {
|
|||||||
return []byte(msg)
|
return []byte(msg)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
path = resolvePath(path)
|
||||||
|
|
||||||
content, ok := args["content"]
|
content, ok := args["content"]
|
||||||
if !ok {
|
if !ok {
|
||||||
content = ""
|
content = ""
|
||||||
@@ -400,6 +403,8 @@ func fileRead(args map[string]string) []byte {
|
|||||||
return []byte(msg)
|
return []byte(msg)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
path = resolvePath(path)
|
||||||
|
|
||||||
content, err := readStringFromFile(path)
|
content, err := readStringFromFile(path)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
msg := "failed to read file; error: " + err.Error()
|
msg := "failed to read file; error: " + err.Error()
|
||||||
@@ -428,6 +433,7 @@ func fileWrite(args map[string]string) []byte {
|
|||||||
logger.Error(msg)
|
logger.Error(msg)
|
||||||
return []byte(msg)
|
return []byte(msg)
|
||||||
}
|
}
|
||||||
|
path = resolvePath(path)
|
||||||
content, ok := args["content"]
|
content, ok := args["content"]
|
||||||
if !ok {
|
if !ok {
|
||||||
content = ""
|
content = ""
|
||||||
@@ -448,6 +454,7 @@ func fileWriteAppend(args map[string]string) []byte {
|
|||||||
logger.Error(msg)
|
logger.Error(msg)
|
||||||
return []byte(msg)
|
return []byte(msg)
|
||||||
}
|
}
|
||||||
|
path = resolvePath(path)
|
||||||
content, ok := args["content"]
|
content, ok := args["content"]
|
||||||
if !ok {
|
if !ok {
|
||||||
content = ""
|
content = ""
|
||||||
@@ -469,6 +476,8 @@ func fileDelete(args map[string]string) []byte {
|
|||||||
return []byte(msg)
|
return []byte(msg)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
path = resolvePath(path)
|
||||||
|
|
||||||
if err := removeFile(path); err != nil {
|
if err := removeFile(path); err != nil {
|
||||||
msg := "failed to delete file; error: " + err.Error()
|
msg := "failed to delete file; error: " + err.Error()
|
||||||
logger.Error(msg)
|
logger.Error(msg)
|
||||||
@@ -486,6 +495,7 @@ func fileMove(args map[string]string) []byte {
|
|||||||
logger.Error(msg)
|
logger.Error(msg)
|
||||||
return []byte(msg)
|
return []byte(msg)
|
||||||
}
|
}
|
||||||
|
src = resolvePath(src)
|
||||||
|
|
||||||
dst, ok := args["dst"]
|
dst, ok := args["dst"]
|
||||||
if !ok || dst == "" {
|
if !ok || dst == "" {
|
||||||
@@ -493,6 +503,7 @@ func fileMove(args map[string]string) []byte {
|
|||||||
logger.Error(msg)
|
logger.Error(msg)
|
||||||
return []byte(msg)
|
return []byte(msg)
|
||||||
}
|
}
|
||||||
|
dst = resolvePath(dst)
|
||||||
|
|
||||||
if err := moveFile(src, dst); err != nil {
|
if err := moveFile(src, dst); err != nil {
|
||||||
msg := "failed to move file; error: " + err.Error()
|
msg := "failed to move file; error: " + err.Error()
|
||||||
@@ -511,6 +522,7 @@ func fileCopy(args map[string]string) []byte {
|
|||||||
logger.Error(msg)
|
logger.Error(msg)
|
||||||
return []byte(msg)
|
return []byte(msg)
|
||||||
}
|
}
|
||||||
|
src = resolvePath(src)
|
||||||
|
|
||||||
dst, ok := args["dst"]
|
dst, ok := args["dst"]
|
||||||
if !ok || dst == "" {
|
if !ok || dst == "" {
|
||||||
@@ -518,6 +530,7 @@ func fileCopy(args map[string]string) []byte {
|
|||||||
logger.Error(msg)
|
logger.Error(msg)
|
||||||
return []byte(msg)
|
return []byte(msg)
|
||||||
}
|
}
|
||||||
|
dst = resolvePath(dst)
|
||||||
|
|
||||||
if err := copyFile(src, dst); err != nil {
|
if err := copyFile(src, dst); err != nil {
|
||||||
msg := "failed to copy file; error: " + err.Error()
|
msg := "failed to copy file; error: " + err.Error()
|
||||||
@@ -535,6 +548,8 @@ func fileList(args map[string]string) []byte {
|
|||||||
path = "." // default to current directory
|
path = "." // default to current directory
|
||||||
}
|
}
|
||||||
|
|
||||||
|
path = resolvePath(path)
|
||||||
|
|
||||||
files, err := listDirectory(path)
|
files, err := listDirectory(path)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
msg := "failed to list directory; error: " + err.Error()
|
msg := "failed to list directory; error: " + err.Error()
|
||||||
@@ -558,6 +573,13 @@ func fileList(args map[string]string) []byte {
|
|||||||
|
|
||||||
// Helper functions for file operations
|
// Helper functions for file operations
|
||||||
|
|
||||||
|
func resolvePath(p string) string {
|
||||||
|
if filepath.IsAbs(p) {
|
||||||
|
return p
|
||||||
|
}
|
||||||
|
return filepath.Join(cfg.CodingDir, p)
|
||||||
|
}
|
||||||
|
|
||||||
func readStringFromFile(filename string) (string, error) {
|
func readStringFromFile(filename string) (string, error) {
|
||||||
data, err := os.ReadFile(filename)
|
data, err := os.ReadFile(filename)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
|||||||
1
tui.go
1
tui.go
@@ -76,6 +76,7 @@ var (
|
|||||||
[yellow]Ctrl+c[white]: close programm
|
[yellow]Ctrl+c[white]: close programm
|
||||||
[yellow]Ctrl+n[white]: start a new chat
|
[yellow]Ctrl+n[white]: start a new chat
|
||||||
[yellow]Ctrl+o[white]: open image file picker
|
[yellow]Ctrl+o[white]: open image file picker
|
||||||
|
[yellow]c[white]: (in file picker) set current dir as CodingDir
|
||||||
[yellow]Ctrl+p[white]: props edit form (min-p, dry, etc.)
|
[yellow]Ctrl+p[white]: props edit form (min-p, dry, etc.)
|
||||||
[yellow]Ctrl+v[white]: show API link selection popup to choose current API
|
[yellow]Ctrl+v[white]: show API link selection popup to choose current API
|
||||||
[yellow]Ctrl+r[white]: start/stop recording from your microphone (needs stt server or whisper binary)
|
[yellow]Ctrl+r[white]: start/stop recording from your microphone (needs stt server or whisper binary)
|
||||||
|
|||||||
Reference in New Issue
Block a user