summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--.gitignore2
-rw-r--r--bot.go5
-rw-r--r--config/config.go23
-rw-r--r--llm.go18
-rw-r--r--main.go11
-rw-r--r--tui.go73
6 files changed, 96 insertions, 36 deletions
diff --git a/.gitignore b/.gitignore
index 77a54f3..8377edb 100644
--- a/.gitignore
+++ b/.gitignore
@@ -1,7 +1,6 @@
*.txt
*.json
testlog
-elefant
history/
*.db
config.toml
@@ -11,4 +10,5 @@ history_bak/
.aider*
tags
gf-lt
+gflt
chat_exports/*.json
diff --git a/bot.go b/bot.go
index 35ea0fa..8373edf 100644
--- a/bot.go
+++ b/bot.go
@@ -203,7 +203,7 @@ func sendMsgToLLM(body io.Reader) {
line, err := reader.ReadBytes('\n')
if err != nil {
logger.Error("error reading response body", "error", err, "line", string(line),
- "reqbody", string(bodyBytes), "user_role", cfg.UserRole, "parser", chunkParser, "link", cfg.CurrentAPI)
+ "user_role", cfg.UserRole, "parser", chunkParser, "link", cfg.CurrentAPI)
// if err.Error() != "EOF" {
streamDone <- true
break
@@ -355,6 +355,9 @@ func chatRound(userMsg, role string, tv *tview.TextView, regen, resume bool) {
logger.Error("empty reader from msgs", "role", role, "error", err)
return
}
+ if cfg.SkipLLMResp {
+ return
+ }
go sendMsgToLLM(reader)
logger.Debug("looking at vars in chatRound", "msg", userMsg, "regen", regen, "resume", resume)
if !resume {
diff --git a/config/config.go b/config/config.go
index 76d7519..cc6e0de 100644
--- a/config/config.go
+++ b/config/config.go
@@ -15,17 +15,18 @@ type Config struct {
CurrentProvider string
APIMap map[string]string
//
- ShowSys bool `toml:"ShowSys"`
- LogFile string `toml:"LogFile"`
- UserRole string `toml:"UserRole"`
- ToolRole string `toml:"ToolRole"`
- ToolUse bool `toml:"ToolUse"`
- ThinkUse bool `toml:"ThinkUse"`
- AssistantRole string `toml:"AssistantRole"`
- SysDir string `toml:"SysDir"`
- ChunkLimit uint32 `toml:"ChunkLimit"`
- WriteNextMsgAs string
- SkipLLMResp bool
+ ShowSys bool `toml:"ShowSys"`
+ LogFile string `toml:"LogFile"`
+ UserRole string `toml:"UserRole"`
+ ToolRole string `toml:"ToolRole"`
+ ToolUse bool `toml:"ToolUse"`
+ ThinkUse bool `toml:"ThinkUse"`
+ AssistantRole string `toml:"AssistantRole"`
+ SysDir string `toml:"SysDir"`
+ ChunkLimit uint32 `toml:"ChunkLimit"`
+ WriteNextMsgAs string
+ WriteNextMsgAsCompletionAgent string
+ SkipLLMResp bool
// embeddings
RAGEnabled bool `toml:"RAGEnabled"`
EmbedURL string `toml:"EmbedURL"`
diff --git a/llm.go b/llm.go
index 05874a1..4cef914 100644
--- a/llm.go
+++ b/llm.go
@@ -92,7 +92,11 @@ func (lcp LlamaCPPeer) FormMsg(msg, role string, resume bool) (io.Reader, error)
prompt := strings.Join(messages, "\n")
// strings builder?
if !resume {
- botMsgStart := "\n" + cfg.AssistantRole + ":\n"
+ botPersona := cfg.AssistantRole
+ if cfg.WriteNextMsgAsCompletionAgent != "" {
+ botPersona = cfg.WriteNextMsgAsCompletionAgent
+ }
+ botMsgStart := "\n" + botPersona + ":\n"
prompt += botMsgStart
}
if cfg.ThinkUse && !cfg.ToolUse {
@@ -234,7 +238,11 @@ func (ds DeepSeekerCompletion) FormMsg(msg, role string, resume bool) (io.Reader
prompt := strings.Join(messages, "\n")
// strings builder?
if !resume {
- botMsgStart := "\n" + cfg.AssistantRole + ":\n"
+ botPersona := cfg.AssistantRole
+ if cfg.WriteNextMsgAsCompletionAgent != "" {
+ botPersona = cfg.WriteNextMsgAsCompletionAgent
+ }
+ botMsgStart := "\n" + botPersona + ":\n"
prompt += botMsgStart
}
if cfg.ThinkUse && !cfg.ToolUse {
@@ -376,7 +384,11 @@ func (or OpenRouterCompletion) FormMsg(msg, role string, resume bool) (io.Reader
prompt := strings.Join(messages, "\n")
// strings builder?
if !resume {
- botMsgStart := "\n" + cfg.AssistantRole + ":\n"
+ botPersona := cfg.AssistantRole
+ if cfg.WriteNextMsgAsCompletionAgent != "" {
+ botPersona = cfg.WriteNextMsgAsCompletionAgent
+ }
+ botMsgStart := "\n" + botPersona + ":\n"
prompt += botMsgStart
}
if cfg.ThinkUse && !cfg.ToolUse {
diff --git a/main.go b/main.go
index b332ac0..82027c6 100644
--- a/main.go
+++ b/main.go
@@ -9,11 +9,12 @@ import (
)
var (
- botRespMode = false
- editMode = false
- selectedIndex = int(-1)
- indexLine = "F12 to show keys help | bot resp mode: [orange:-:b]%v[-:-:-] (F6) | char: [orange:-:b]%s[-:-:-] (ctrl+s) | chat: [orange:-:b]%s[-:-:-] (F1) | toolUseAdviced: [orange:-:b]%v[-:-:-] (ctrl+k) | model: [orange:-:b]%s[-:-:-] (ctrl+l) | skip LLM resp: [orange:-:b]%v[-:-:-] (F10)\nAPI_URL: [orange:-:b]%s[-:-:-] (ctrl+v) | ThinkUse: [orange:-:b]%v[-:-:-] (ctrl+p) | Log Level: [orange:-:b]%v[-:-:-] (ctrl+p) | Recording: [orange:-:b]%v[-:-:-] (ctrl+r) | Writing as: [orange:-:b]%s[-:-:-] (ctrl+q)"
- focusSwitcher = map[tview.Primitive]tview.Primitive{}
+ botRespMode = false
+ editMode = false
+ selectedIndex = int(-1)
+ indexLine = "F12 to show keys help | bot resp mode: [orange:-:b]%v[-:-:-] (F6) | card's char: [orange:-:b]%s[-:-:-] (ctrl+s) | chat: [orange:-:b]%s[-:-:-] (F1) | toolUseAdviced: [orange:-:b]%v[-:-:-] (ctrl+k) | model: [orange:-:b]%s[-:-:-] (ctrl+l) | skip LLM resp: [orange:-:b]%v[-:-:-] (F10)\nAPI_URL: [orange:-:b]%s[-:-:-] (ctrl+v) | ThinkUse: [orange:-:b]%v[-:-:-] (ctrl+p) | Log Level: [orange:-:b]%v[-:-:-] (ctrl+p) | Recording: [orange:-:b]%v[-:-:-] (ctrl+r) | Writing as: [orange:-:b]%s[-:-:-] (ctrl+q)"
+ indexLineCompletion = "F12 to show keys help | bot resp mode: [orange:-:b]%v[-:-:-] (F6) | card's char: [orange:-:b]%s[-:-:-] (ctrl+s) | chat: [orange:-:b]%s[-:-:-] (F1) | toolUseAdviced: [orange:-:b]%v[-:-:-] (ctrl+k) | model: [orange:-:b]%s[-:-:-] (ctrl+l) | skip LLM resp: [orange:-:b]%v[-:-:-] (F10)\nAPI_URL: [orange:-:b]%s[-:-:-] (ctrl+v) | ThinkUse: [orange:-:b]%v[-:-:-] (ctrl+p) | Log Level: [orange:-:b]%v[-:-:-] (ctrl+p) | Recording: [orange:-:b]%v[-:-:-] (ctrl+r) | Writing as: [orange:-:b]%s[-:-:-] (ctrl+q) | Bot will write as [orange:-:b]%s[-:-:-] (ctrl+x)"
+ focusSwitcher = map[tview.Primitive]tview.Primitive{}
)
func isASCII(s string) bool {
diff --git a/tui.go b/tui.go
index ee0e5e6..5f6ceb1 100644
--- a/tui.go
+++ b/tui.go
@@ -98,6 +98,15 @@ func loadImage() {
imgView.SetImage(img)
}
+func strInSlice(s string, sl []string) bool {
+ for _, el := range sl {
+ if strings.EqualFold(s, el) {
+ return true
+ }
+ }
+ return false
+}
+
func colorText() {
text := textView.GetText(false)
// Step 1: Extract code blocks and replace them with unique placeholders
@@ -151,8 +160,17 @@ func updateStatusLine() {
if cfg.WriteNextMsgAs != "" {
persona = cfg.WriteNextMsgAs
}
- position.SetText(fmt.Sprintf(indexLine, botRespMode, cfg.AssistantRole, activeChatName, cfg.ToolUse, chatBody.Model,
- cfg.SkipLLMResp, cfg.CurrentAPI, cfg.ThinkUse, logLevel.Level(), isRecording, persona))
+ if strings.Contains(cfg.CurrentAPI, "chat") {
+ position.SetText(fmt.Sprintf(indexLine, botRespMode, cfg.AssistantRole, activeChatName, cfg.ToolUse, chatBody.Model,
+ cfg.SkipLLMResp, cfg.CurrentAPI, cfg.ThinkUse, logLevel.Level(), isRecording, persona))
+ return
+ }
+ botPersona := cfg.AssistantRole
+ if cfg.WriteNextMsgAsCompletionAgent != "" {
+ botPersona = cfg.WriteNextMsgAsCompletionAgent
+ }
+ position.SetText(fmt.Sprintf(indexLineCompletion, botRespMode, cfg.AssistantRole, activeChatName, cfg.ToolUse, chatBody.Model,
+ cfg.SkipLLMResp, cfg.CurrentAPI, cfg.ThinkUse, logLevel.Level(), isRecording, persona, botPersona))
}
func initSysCards() ([]string, error) {
@@ -354,7 +372,6 @@ func init() {
editArea.SetInputCapture(func(event *tcell.EventKey) *tcell.EventKey {
// if event.Key() == tcell.KeyEscape && editMode {
if event.Key() == tcell.KeyEscape {
- logger.Warn("edit debug; esc is pressed")
defer colorText()
editedMsg := editArea.GetText()
if editedMsg == "" {
@@ -424,10 +441,7 @@ func init() {
if err := copyToClipboard(m.Content); err != nil {
logger.Error("failed to copy to clipboard", "error", err)
}
- previewLen := 30
- if len(m.Content) < 30 {
- previewLen = len(m.Content)
- }
+ previewLen := min(30, len(m.Content))
notification := fmt.Sprintf("msg '%s' was copied to the clipboard", m.Content[:previewLen])
if err := notifyUser("copied", notification); err != nil {
logger.Error("failed to send notification", "error", err)
@@ -573,10 +587,7 @@ func init() {
if err := copyToClipboard(m.Content); err != nil {
logger.Error("failed to copy to clipboard", "error", err)
}
- previewLen := 30
- if len(m.Content) < 30 {
- previewLen = len(m.Content)
- }
+ previewLen := min(30, len(m.Content))
notification := fmt.Sprintf("msg '%s' was copied to the clipboard", m.Content[:previewLen])
if err := notifyUser("copied", notification); err != nil {
logger.Error("failed to send notification", "error", err)
@@ -798,7 +809,12 @@ func init() {
roles := chatBody.ListRoles()
if len(roles) == 0 {
logger.Warn("empty roles in chat")
+ return nil
+ }
+ if !strInSlice(cfg.UserRole, roles) {
+ roles = append(roles, cfg.UserRole)
}
+ logger.Info("list roles", "roles", roles)
for i, role := range roles {
if strings.EqualFold(role, persona) {
if i == len(roles)-1 {
@@ -806,6 +822,33 @@ func init() {
break
}
cfg.WriteNextMsgAs = roles[i+1] // get next role
+ logger.Info("picked role", "roles", roles, "index", i+1)
+ break
+ }
+ }
+ updateStatusLine()
+ return nil
+ }
+ if event.Key() == tcell.KeyCtrlX {
+ persona := cfg.AssistantRole
+ if cfg.WriteNextMsgAsCompletionAgent != "" {
+ persona = cfg.WriteNextMsgAsCompletionAgent
+ }
+ roles := chatBody.ListRoles()
+ if len(roles) == 0 {
+ logger.Warn("empty roles in chat")
+ }
+ if !strInSlice(cfg.AssistantRole, roles) {
+ roles = append(roles, cfg.AssistantRole)
+ }
+ for i, role := range roles {
+ if strings.EqualFold(role, persona) {
+ if i == len(roles)-1 {
+ cfg.WriteNextMsgAsCompletionAgent = roles[0] // reached last, get first
+ break
+ }
+ cfg.WriteNextMsgAsCompletionAgent = roles[i+1] // get next role
+ logger.Info("picked role", "roles", roles, "index", i+1)
break
}
}
@@ -836,10 +879,10 @@ func init() {
textView.ScrollToEnd()
colorText()
}
- if !cfg.SkipLLMResp {
- // update statue line
- go chatRound(msgText, persona, textView, false, false)
- }
+ go chatRound(msgText, persona, textView, false, false)
+ // if !cfg.SkipLLMResp {
+ // // update statue line
+ // }
return nil
}
if event.Key() == tcell.KeyPgUp || event.Key() == tcell.KeyPgDn {