summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--README.md3
-rw-r--r--storage/storage.go6
-rw-r--r--storage/storage_test.go1
-rw-r--r--tools.go7
-rw-r--r--tui.go68
5 files changed, 58 insertions, 27 deletions
diff --git a/README.md b/README.md
index 4eeea47..0f16cb1 100644
--- a/README.md
+++ b/README.md
@@ -48,6 +48,7 @@
- when bot generation ended with err: need a way to switch back to the bot_resp_false mode; +
- no selection focus on modal sys buttons after opening it a second time; (cannot reproduce) +
- chat should contain char in it (one to many: char: []chats); +
-- all page names should be vars;
+- all page names should be vars; +
- normal case regen omits assistant icon; +
- user icon (and role?) from config is not used; +
+- F1 can load any chat, by loading chat of other agent it does not switch agents, if that chat is continued, it will rewrite agent in db; (either allow only chats from current agent OR switch agent on chat loading);
diff --git a/storage/storage.go b/storage/storage.go
index b876dbc..0853328 100644
--- a/storage/storage.go
+++ b/storage/storage.go
@@ -53,11 +53,15 @@ func (p ProviderSQL) GetLastChatByAgent(agent string) (*models.Chat, error) {
return &resp, err
}
+// https://sqlite.org/lang_upsert.html
+// on conflict was added
func (p ProviderSQL) UpsertChat(chat *models.Chat) (*models.Chat, error) {
// Prepare the SQL statement
query := `
- INSERT OR REPLACE INTO chats (id, name, msgs, agent, created_at, updated_at)
+ INSERT INTO chats (id, name, msgs, agent, created_at, updated_at)
VALUES (:id, :name, :msgs, :agent, :created_at, :updated_at)
+ ON CONFLICT(id) DO UPDATE SET msgs=excluded.msgs,
+ updated_at=excluded.updated_at
RETURNING *;`
stmt, err := p.db.PrepareNamed(query)
if err != nil {
diff --git a/storage/storage_test.go b/storage/storage_test.go
index ad1f1bf..8373ab0 100644
--- a/storage/storage_test.go
+++ b/storage/storage_test.go
@@ -95,6 +95,7 @@ func TestChatHistory(t *testing.T) {
id INTEGER PRIMARY KEY AUTOINCREMENT,
name TEXT NOT NULL,
msgs TEXT NOT NULL,
+ agent TEXT NOT NULL,
created_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
updated_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP
);`)
diff --git a/tools.go b/tools.go
index bb9012e..39c6063 100644
--- a/tools.go
+++ b/tools.go
@@ -9,9 +9,10 @@ import (
)
var (
- toolCallRE = regexp.MustCompile(`__tool_call__\s*([\s\S]*?)__tool_call__`)
- quotesRE = regexp.MustCompile(`(".*?")`)
- starRE = regexp.MustCompile(`(\*.*?\*)`)
+ toolCallRE = regexp.MustCompile(`__tool_call__\s*([\s\S]*?)__tool_call__`)
+ quotesRE = regexp.MustCompile(`(".*?")`)
+ starRE = regexp.MustCompile(`(\*.*?\*)`)
+ // codeBlokRE = regexp.MustCompile(`(\x60\x60\x60.*?\x60\x60\x60)`)
basicSysMsg = `Large Language Model that helps user with any of his requests.`
toolSysMsg = `You're a helpful assistant.
# Tools
diff --git a/tui.go b/tui.go
index 9493ffb..73ea66e 100644
--- a/tui.go
+++ b/tui.go
@@ -25,7 +25,15 @@ var (
sysModal *tview.Modal
indexPickWindow *tview.InputField
renameWindow *tview.InputField
- helpText = `
+ // pages
+ historyPage = "historyPage"
+ agentPage = "agentPage"
+ editMsgPage = "editMsgPage"
+ indexPage = "indexPage"
+ helpPage = "helpPage"
+ renamePage = "renamePage"
+ // help text
+ helpText = `
[yellow]Esc[white]: send msg
[yellow]PgUp/Down[white]: switch focus
[yellow]F1[white]: manage chats
@@ -39,15 +47,31 @@ var (
[yellow]Ctrl+s[white]: load new char/agent
[yellow]Ctrl+e[white]: export chat to json file
[yellow]Ctrl+n[white]: start a new chat
+[yellow]Ctrl+c[white]: close programm
Press Enter to go back
`
)
+// // code block colors get interrupted by " & *
+// func codeBlockColor(text string) string {
+// fi := strings.Index(text, "```")
+// if fi < 0 {
+// return text
+// }
+// li := strings.LastIndex(text, "```")
+// if li == fi { // only openning backticks
+// return text
+// }
+// return strings.Replace(text, "```", "```[blue:black:i]", 1)
+// }
+
func colorText() {
// INFO: is there a better way to markdown?
tv := textView.GetText(false)
cq := quotesRE.ReplaceAllString(tv, `[orange:-:-]$1[-:-:-]`)
+ // cb := codeBlockColor(cq)
+ // cb := codeBlockRE.ReplaceAllString(cq, `[blue:black:i]$1[-:-:-]`)
textView.SetText(starRE.ReplaceAllString(cq, `[turquoise::i]$1[-:-:-]`))
}
@@ -143,29 +167,29 @@ func init() {
switch buttonLabel {
case "new":
startNewChat()
- pages.RemovePage("history")
+ pages.RemovePage(historyPage)
return
// set text
case "cancel":
- pages.RemovePage("history")
+ pages.RemovePage(historyPage)
return
case "rename current":
// add input field
- pages.RemovePage("history")
- pages.AddPage("renameW", renameWindow, true, true)
+ pages.RemovePage(historyPage)
+ pages.AddPage(renamePage, renameWindow, true, true)
return
default:
fn := buttonLabel
history, err := loadHistoryChat(fn)
if err != nil {
logger.Error("failed to read history file", "chat", fn)
- pages.RemovePage("history")
+ pages.RemovePage(historyPage)
return
}
chatBody.Messages = history
textView.SetText(chatToText(cfg.ShowSys))
activeChatName = fn
- pages.RemovePage("history")
+ pages.RemovePage(historyPage)
colorText()
return
}
@@ -175,13 +199,13 @@ func init() {
SetDoneFunc(func(buttonIndex int, buttonLabel string) {
switch buttonLabel {
case "cancel":
- pages.RemovePage("sys")
+ pages.RemovePage(agentPage)
sysModal.ClearButtons()
return
default:
if ok := charToStart(buttonLabel); !ok {
logger.Warn("no such sys msg", "name", buttonLabel)
- pages.RemovePage("sys")
+ pages.RemovePage(agentPage)
return
}
// replace textview
@@ -189,7 +213,7 @@ func init() {
colorText()
updateStatusLine()
sysModal.ClearButtons()
- pages.RemovePage("sys")
+ pages.RemovePage(agentPage)
app.SetFocus(textArea)
}
})
@@ -203,14 +227,14 @@ func init() {
if err := notifyUser("edit", "no edit provided"); err != nil {
logger.Error("failed to send notification", "error", err)
}
- pages.RemovePage("editArea")
+ pages.RemovePage(editMsgPage)
editMode = false
return nil
}
chatBody.Messages[selectedIndex].Content = editedMsg
// change textarea
textView.SetText(chatToText(cfg.ShowSys))
- pages.RemovePage("editArea")
+ pages.RemovePage(editMsgPage)
editMode = false
return nil
}
@@ -221,7 +245,7 @@ func init() {
SetFieldWidth(4).
SetAcceptanceFunc(tview.InputFieldInteger).
SetDoneFunc(func(key tcell.Key) {
- pages.RemovePage("getIndex")
+ pages.RemovePage(indexPage)
})
indexPickWindow.SetInputCapture(func(event *tcell.EventKey) *tcell.EventKey {
switch event.Key() {
@@ -239,12 +263,12 @@ func init() {
if err := notifyUser("error", msg); err != nil {
logger.Error("failed to send notification", "error", err)
}
- pages.RemovePage("getIndex")
+ pages.RemovePage(indexPage)
return event
}
m := chatBody.Messages[selectedIndex]
if editMode && event.Key() == tcell.KeyEnter {
- pages.AddPage("editArea", editArea, true, true)
+ pages.AddPage(editMsgPage, editArea, true, true)
editArea.SetText(m.Content, true)
}
if !editMode && event.Key() == tcell.KeyEnter {
@@ -271,7 +295,7 @@ func init() {
SetFieldWidth(20).
SetAcceptanceFunc(tview.InputFieldMaxLength(100)).
SetDoneFunc(func(key tcell.Key) {
- pages.RemovePage("renameW")
+ pages.RemovePage(renamePage)
})
renameWindow.SetInputCapture(func(event *tcell.EventKey) *tcell.EventKey {
if event.Key() == tcell.KeyEnter {
@@ -297,7 +321,7 @@ func init() {
})
//
helpView = tview.NewTextView().SetDynamicColors(true).SetText(helpText).SetDoneFunc(func(key tcell.Key) {
- pages.RemovePage("helpView")
+ pages.RemovePage(helpPage)
})
helpView.SetInputCapture(func(event *tcell.EventKey) *tcell.EventKey {
switch event.Key() {
@@ -326,7 +350,7 @@ func init() {
chatOpts := append(chatOpts, chatList...)
chatActModal.ClearButtons()
chatActModal.AddButtons(chatOpts)
- pages.AddPage("history", chatActModal, true, true)
+ pages.AddPage(historyPage, chatActModal, true, true)
return nil
}
if event.Key() == tcell.KeyF2 {
@@ -354,7 +378,7 @@ func init() {
if event.Key() == tcell.KeyF4 {
// edit msg
editMode = true
- pages.AddPage("getIndex", indexPickWindow, true, true)
+ pages.AddPage(indexPage, indexPickWindow, true, true)
return nil
}
if event.Key() == tcell.KeyF5 {
@@ -388,12 +412,12 @@ func init() {
if event.Key() == tcell.KeyF8 {
// copy msg to clipboard
editMode = false
- pages.AddPage("getIndex", indexPickWindow, true, true)
+ pages.AddPage(indexPage, indexPickWindow, true, true)
return nil
}
if event.Key() == tcell.KeyF12 {
// help window cheatsheet
- pages.AddPage("helpView", helpView, true, true)
+ pages.AddPage(helpPage, helpView, true, true)
return nil
}
if event.Key() == tcell.KeyCtrlE {
@@ -427,7 +451,7 @@ func init() {
}
sysModal.AddButtons(labels)
// load all chars
- pages.AddPage("sys", sysModal, true, true)
+ pages.AddPage(agentPage, sysModal, true, true)
updateStatusLine()
return nil
}