summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--README.md13
-rw-r--r--bot.go39
-rw-r--r--main.go57
3 files changed, 78 insertions, 31 deletions
diff --git a/README.md b/README.md
index e918dee..db53835 100644
--- a/README.md
+++ b/README.md
@@ -5,8 +5,15 @@
- show msg id next to the msg; +
- regen last message; +
- delete last message; +
-- edit message? (including from bot);
-- use chatml template (but do not show it to the user);
+- edit message? (including from bot); +
- ability to copy message;
-- aility to copy selected text;
+- aility to copy selected text; (I can do it though vim mode of the terminal, so +)
- menu with old chats (chat files); +
+- fullscreen textarea option (for long prompt);
+- tab to switch selection between textview and textarea (input and chat); +
+- basic tools: memorize and recall;
+- stop stream from the bot;
+
+### FIX:
+- bot responding (or haninging) blocks everything; +
+- programm requires history folder, but it is .gitignore;
diff --git a/bot.go b/bot.go
index 8a09e24..be35a09 100644
--- a/bot.go
+++ b/bot.go
@@ -310,28 +310,27 @@ func chatToText(showSys bool) string {
return strings.Join(s, "")
}
-func textToChat(chat []string) []models.MessagesStory {
+func textToMsg(rawMsg string) models.MessagesStory {
+ msg := models.MessagesStory{}
+ // system and tool?
+ if strings.HasPrefix(rawMsg, assistantIcon) {
+ msg.Role = assistantRole
+ msg.Content = strings.TrimPrefix(rawMsg, assistantIcon)
+ return msg
+ }
+ if strings.HasPrefix(rawMsg, userIcon) {
+ msg.Role = userRole
+ msg.Content = strings.TrimPrefix(rawMsg, userIcon)
+ return msg
+ }
+ return msg
+}
+
+func textSliceToChat(chat []string) []models.MessagesStory {
resp := make([]models.MessagesStory, len(chat))
for i, rawMsg := range chat {
- // trim icon
- var (
- role string
- msg string
- )
- // system and tool?
- if strings.HasPrefix(rawMsg, assistantIcon) {
- role = assistantRole
- msg = strings.TrimPrefix(rawMsg, assistantIcon)
- goto messagebuild
- }
- if strings.HasPrefix(rawMsg, userIcon) {
- role = assistantRole
- msg = strings.TrimPrefix(rawMsg, userIcon)
- goto messagebuild
- }
- messagebuild:
- resp[i].Role = role
- resp[i].Content = msg
+ msg := textToMsg(rawMsg)
+ resp[i] = msg
}
return resp
}
diff --git a/main.go b/main.go
index 672c02a..f808902 100644
--- a/main.go
+++ b/main.go
@@ -14,9 +14,11 @@ import (
var (
normalMode = false
botRespMode = false
+ editMode = false
botMsg = "no"
selectedIndex = int(-1)
- indexLine = "manage chats: F1; regen last: F2; delete msg menu: F3; Row: [yellow]%d[white], Column: [yellow]%d; normal mode: %v"
+ indexLine = "Esc: send msg; Tab: switch focus; F1: manage chats; F2: regen last; F3:delete msg menu; F4: edit msg; F5: toggle system; Row: [yellow]%d[white], Column: [yellow]%d; normal mode: %v"
+ focusSwitcher = map[tview.Primitive]tview.Primitive{}
)
func isASCII(s string) bool {
@@ -41,6 +43,8 @@ func main() {
app.Draw()
})
textView.SetBorder(true).SetTitle("chat")
+ focusSwitcher[textArea] = textView
+ focusSwitcher[textView] = textArea
position := tview.NewTextView().
SetDynamicColors(true).
SetTextAlign(tview.AlignCenter)
@@ -53,7 +57,7 @@ func main() {
if fromRow == toRow && fromColumn == toColumn {
position.SetText(fmt.Sprintf(indexLine, fromRow, fromColumn, normalMode))
} else {
- position.SetText(fmt.Sprintf("manage chats: F1; regen last: F2; delete msg menu: F3; [red]From[white] Row: [yellow]%d[white], Column: [yellow]%d[white] - [red]To[white] Row: [yellow]%d[white], To Column: [yellow]%d; normal mode: %v", fromRow, fromColumn, toRow, toColumn, normalMode))
+ position.SetText(fmt.Sprintf("Esc: send msg; Tab: switch focus; F1: manage chats; F2: regen last; F3:delete msg menu; F4: edit msg; F5: toggle system; Row: [yellow]%d[white], Column: [yellow]%d[white] - [red]To[white] Row: [yellow]%d[white], To Column: [yellow]%d; normal mode: %v", fromRow, fromColumn, toRow, toColumn, normalMode))
}
}
chatOpts := []string{"cancel", "new"}
@@ -95,6 +99,24 @@ func main() {
return
}
})
+ editArea := tview.NewTextArea().
+ SetPlaceholder("Replace msg...")
+ editArea.SetBorder(true).SetTitle("input")
+ editArea.SetInputCapture(func(event *tcell.EventKey) *tcell.EventKey {
+ if event.Key() == tcell.KeyEscape && editMode {
+ editedMsg := editArea.GetText()
+ // TODO: trim msg number and icon
+ chatBody.Messages[selectedIndex].Content = editedMsg
+ // change textarea
+ textView.SetText(chatToText(showSystemMsgs))
+ pages.RemovePage("editArea")
+ editMode = false
+ // panic("do we get here?")
+ // pages.ShowPage("main")
+ return nil
+ }
+ return event
+ })
indexPickWindow := tview.NewInputField().
SetLabel("Enter a msg index: ").
SetFieldWidth(4).
@@ -110,6 +132,16 @@ func main() {
if err != nil {
logger.Error("failed to convert provided index", "error", err, "si", si)
}
+ if len(chatBody.Messages) <= selectedIndex && selectedIndex < 0 {
+ logger.Warn("chosen index is out of bounds", "index", selectedIndex)
+ return nil
+ }
+ pages.AddPage("editArea", editArea, true, true)
+ m := chatBody.Messages[selectedIndex]
+ // editArea.SetText(m.ToText(selectedIndex), true)
+ editArea.SetText(m.Content, true)
+ editMode = true
+ // editArea.SetText(si, true)
}
return event
})
@@ -119,10 +151,6 @@ func main() {
textView.SetText(chatToText(showSystemMsgs))
textView.ScrollToEnd()
app.SetInputCapture(func(event *tcell.EventKey) *tcell.EventKey {
- if botRespMode {
- // do nothing while bot typing
- return nil
- }
if event.Key() == tcell.KeyF1 {
fList, err := listHistoryFiles(historyDir)
if err != nil {
@@ -144,13 +172,22 @@ func main() {
// modal window with input field
chatBody.Messages = chatBody.Messages[:len(chatBody.Messages)-1]
textView.SetText(chatToText(showSystemMsgs))
+ botRespMode = false // hmmm; is that correct?
return nil
}
if event.Key() == tcell.KeyF4 {
// edit msg
pages.AddPage("getIndex", indexPickWindow, true, true)
+ editMode = true
+ return nil
}
- if event.Key() == tcell.KeyEscape {
+ if event.Key() == tcell.KeyF5 {
+ // switch showSystemMsgs
+ showSystemMsgs = !showSystemMsgs
+ textView.SetText(chatToText(showSystemMsgs))
+ }
+ // cannot send msg in editMode or botRespMode
+ if event.Key() == tcell.KeyEscape && !editMode && !botRespMode {
fromRow, fromColumn, _, _ := textArea.GetCursor()
position.SetText(fmt.Sprintf(indexLine, fromRow, fromColumn, normalMode))
// read all text into buffer
@@ -164,7 +201,11 @@ func main() {
go chatRound(msgText, userRole, textView)
return nil
}
- if isASCII(string(event.Rune())) {
+ if event.Key() == tcell.KeyTab {
+ currentF := app.GetFocus()
+ app.SetFocus(focusSwitcher[currentF])
+ }
+ if isASCII(string(event.Rune())) && !botRespMode {
// normalMode = false
// fromRow, fromColumn, _, _ := textArea.GetCursor()
// position.SetText(fmt.Sprintf(indexLine, fromRow, fromColumn, normalMode))