From 990e0695c582c2c8d647c258cde0342ac14e3a75 Mon Sep 17 00:00:00 2001 From: Grail Finder Date: Thu, 5 Dec 2024 18:36:05 +0300 Subject: Enha: add agent to chat history; gen-regen diff --- README.md | 3 +++ bot.go | 8 ++++---- main.go | 2 +- models/db.go | 1 + storage/migrations/001_init.up.sql | 1 + tui.go | 23 +++++++++++++++-------- 6 files changed, 25 insertions(+), 13 deletions(-) diff --git a/README.md b/README.md index 176ec2e..2f0dc2e 100644 --- a/README.md +++ b/README.md @@ -43,3 +43,6 @@ - if option to show sys msg enabled: it show display new tool responses; - 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; +- chat should contain char in it (one to many: char: []chats); +- char card is the sys message, but how about giving tools to char that does not have it? +- it is a bit clumsy to mix chats in db and chars from the external files, maybe load external files in db on startup? diff --git a/bot.go b/bot.go index 2179fd3..6ff579d 100644 --- a/bot.go +++ b/bot.go @@ -102,7 +102,7 @@ func sendMsgToLLM(body io.Reader) { } } -func chatRound(userMsg, role string, tv *tview.TextView) { +func chatRound(userMsg, role string, tv *tview.TextView, regen bool) { botRespMode = true reader := formMsg(chatBody, userMsg, role) if reader == nil { @@ -110,7 +110,7 @@ func chatRound(userMsg, role string, tv *tview.TextView) { return } go sendMsgToLLM(reader) - if userMsg != "" { // no need to write assistant icon since we continue old message + if userMsg != "" && !regen { // no need to write assistant icon since we continue old message fmt.Fprintf(tv, "(%d) ", len(chatBody.Messages)) fmt.Fprint(tv, cfg.AssistantIcon) } @@ -158,12 +158,12 @@ func findCall(msg string, tv *tview.TextView) { f, ok := fnMap[fc.Name] if !ok { m := fc.Name + "%s is not implemented" - chatRound(m, cfg.ToolRole, tv) + chatRound(m, cfg.ToolRole, tv, false) return } resp := f(fc.Args...) toolMsg := fmt.Sprintf("tool response: %+v", string(resp)) - chatRound(toolMsg, cfg.ToolRole, tv) + chatRound(toolMsg, cfg.ToolRole, tv, false) } func chatToTextSlice(showSys bool) []string { diff --git a/main.go b/main.go index 4b21457..dd296e9 100644 --- a/main.go +++ b/main.go @@ -10,7 +10,7 @@ var ( botRespMode = false editMode = false selectedIndex = int(-1) - indexLine = "F12 to show keys help; bot resp mode: %v; current chat: %s" + indexLine = "F12 to show keys help; bot resp mode: %v; char: %s; chat: %s" focusSwitcher = map[tview.Primitive]tview.Primitive{} ) diff --git a/models/db.go b/models/db.go index 4f52f68..1f1c8b4 100644 --- a/models/db.go +++ b/models/db.go @@ -9,6 +9,7 @@ type Chat struct { ID uint32 `db:"id" json:"id"` Name string `db:"name" json:"name"` Msgs string `db:"msgs" json:"msgs"` // []RoleMsg to string json + Agent string `db:"agent" json:"agent"` CreatedAt time.Time `db:"created_at" json:"created_at"` UpdatedAt time.Time `db:"updated_at" json:"updated_at"` } diff --git a/storage/migrations/001_init.up.sql b/storage/migrations/001_init.up.sql index 8980ccf..09bb5e6 100644 --- a/storage/migrations/001_init.up.sql +++ b/storage/migrations/001_init.up.sql @@ -2,6 +2,7 @@ CREATE TABLE IF NOT EXISTS chats ( id INTEGER PRIMARY KEY AUTOINCREMENT, name TEXT NOT NULL, msgs TEXT NOT NULL, + agent TEXT NOT NULL DEFAULT 'assistant', created_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP, updated_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP ); diff --git a/tui.go b/tui.go index caebb82..ef8c282 100644 --- a/tui.go +++ b/tui.go @@ -33,7 +33,8 @@ var ( [yellow]F4[white]: edit msg [yellow]F5[white]: toggle system [yellow]F6[white]: interrupt bot resp -[yellow]F7[white]: copy msg to clipboard (linux xclip) +[yellow]F7[white]: copy last msg to clipboard (linux xclip) +[yellow]F8[white]: copy n msg to clipboard (linux xclip) [yellow]Ctrl+s[white]: choose/replace system prompt Press Enter to go back @@ -77,7 +78,7 @@ func init() { AddItem(textArea, 0, 10, true). AddItem(position, 0, 1, false) updateStatusLine := func() { - position.SetText(fmt.Sprintf(indexLine, botRespMode, activeChatName)) + position.SetText(fmt.Sprintf(indexLine, botRespMode, cfg.AssistantRole, activeChatName)) // INFO: way too ineffective; it should be optional or removed // tv := textView.GetText(false) // cq := quotesRE.ReplaceAllString(tv, `[orange]$1[white]`) @@ -103,9 +104,10 @@ func init() { chatBody.Messages = defaultStarter textView.SetText(chatToText(cfg.ShowSys)) newChat := &models.Chat{ - ID: id + 1, - Name: fmt.Sprintf("%v_%v", "new", time.Now().Unix()), - Msgs: string(defaultStarterBytes), + ID: id + 1, + Name: fmt.Sprintf("%v_%v", "new", time.Now().Unix()), + Msgs: string(defaultStarterBytes), + Agent: cfg.AssistantRole, } // activeChatName = path.Join(historyDir, fmt.Sprintf("%d_chat.json", time.Now().Unix())) activeChatName = newChat.Name @@ -282,7 +284,7 @@ func init() { // regen last msg chatBody.Messages = chatBody.Messages[:len(chatBody.Messages)-1] textView.SetText(chatToText(cfg.ShowSys)) - go chatRound("", cfg.UserRole, textView) + go chatRound("", cfg.UserRole, textView, true) return nil } if event.Key() == tcell.KeyF3 && !botRespMode { @@ -335,6 +337,11 @@ func init() { textArea.SetText("pressed ctrl+e", true) return nil } + if event.Key() == tcell.KeyCtrlA { + textArea.SetText("pressed ctrl+a", true) + // list all agents + return nil + } if event.Key() == tcell.KeyCtrlS { // switch sys prompt cards, err := pngmeta.ReadDirCards(cfg.SysDir, cfg.UserRole) @@ -358,7 +365,7 @@ func init() { } // cannot send msg in editMode or botRespMode if event.Key() == tcell.KeyEscape && !editMode && !botRespMode { - position.SetText(fmt.Sprintf(indexLine, botRespMode, activeChatName)) + position.SetText(fmt.Sprintf(indexLine, botRespMode, cfg.AssistantRole, activeChatName)) // read all text into buffer msgText := textArea.GetText() if msgText != "" { @@ -367,7 +374,7 @@ func init() { textView.ScrollToEnd() } // update statue line - go chatRound(msgText, cfg.UserRole, textView) + go chatRound(msgText, cfg.UserRole, textView, false) return nil } if event.Key() == tcell.KeyPgUp || event.Key() == tcell.KeyPgDn { -- cgit v1.2.3