diff options
| -rw-r--r-- | bot.go | 61 | ||||
| -rw-r--r-- | tools.go | 13 | ||||
| -rw-r--r-- | tui.go | 6 |
3 files changed, 34 insertions, 46 deletions
@@ -69,7 +69,6 @@ var ( "meta-llama/llama-3.3-70b-instruct:free", } LocalModels = []string{} - lastSummary string ) // cleanNullMessages removes messages with null or empty content to prevent API issues @@ -627,22 +626,8 @@ func checkGame(role string, tv *tview.TextView) { } } -func chatRound(userMsg, role string, tv *tview.TextView, regen, resume, summaryMode bool) { +func chatRound(userMsg, role string, tv *tview.TextView, regen, resume bool) { botRespMode = true - if summaryMode { - // Save original messages - originalMessages := chatBody.Messages - defer func() { chatBody.Messages = originalMessages }() - // Build summary prompt messages - summaryMessages := []models.RoleMsg{} - // Add system instruction - summaryMessages = append(summaryMessages, models.RoleMsg{Role: "system", Content: "Please provide a concise summary of the following conversation. Focus on key points, decisions, and actions. Provide only the summary, no additional commentary."}) - // Append all original messages (excluding system? keep them) - summaryMessages = append(summaryMessages, originalMessages...) - // Add a user message to trigger summary - summaryMessages = append(summaryMessages, models.RoleMsg{Role: cfg.UserRole, Content: "Summarize the conversation."}) - chatBody.Messages = summaryMessages - } botPersona := cfg.AssistantRole if cfg.WriteNextMsgAsCompletionAgent != "" { botPersona = cfg.WriteNextMsgAsCompletionAgent @@ -672,7 +657,7 @@ func chatRound(userMsg, role string, tv *tview.TextView, regen, resume, summaryM } go sendMsgToLLM(reader) logger.Debug("looking at vars in chatRound", "msg", userMsg, "regen", regen, "resume", resume) - if !summaryMode && !resume { + if !resume { fmt.Fprintf(tv, "\n[-:-:b](%d) ", len(chatBody.Messages)) fmt.Fprint(tv, roleToIcon(botPersona)) fmt.Fprint(tv, "[-:-:-]\n") @@ -719,9 +704,6 @@ out: Role: botPersona, Content: respText.String(), }) } - if summaryMode { - lastSummary = respText.String() - } logger.Debug("chatRound: before cleanChatBody", "messages_before_clean", len(chatBody.Messages)) for i, msg := range chatBody.Messages { logger.Debug("chatRound: before cleaning", "index", i, "role", msg.Role, "content_len", len(msg.Content), "has_content", msg.HasContent(), "tool_call_id", msg.ToolCallID) @@ -732,19 +714,15 @@ out: for i, msg := range chatBody.Messages { logger.Debug("chatRound: after cleaning", "index", i, "role", msg.Role, "content_len", len(msg.Content), "has_content", msg.HasContent(), "tool_call_id", msg.ToolCallID) } - if !summaryMode { - colorText() - updateStatusLine() - } + colorText() + updateStatusLine() // bot msg is done; // now check it for func call // logChat(activeChatName, chatBody.Messages) - if !summaryMode { - if err := updateStorageChat(activeChatName, chatBody.Messages); err != nil { - logger.Warn("failed to update storage", "error", err, "name", activeChatName) - } - findCall(respText.String(), toolResp.String(), tv) + if err := updateStorageChat(activeChatName, chatBody.Messages); err != nil { + logger.Warn("failed to update storage", "error", err, "name", activeChatName) } + findCall(respText.String(), toolResp.String(), tv) } // cleanChatBody removes messages with null or empty content to prevent API issues @@ -847,7 +825,7 @@ func findCall(msg, toolCall string, tv *tview.TextView) { chatBody.Messages = append(chatBody.Messages, toolResponseMsg) // Clear the stored tool call ID after using it (no longer needed) // Trigger the assistant to continue processing with the error message - chatRound("", cfg.AssistantRole, tv, false, false, false) + chatRound("", cfg.AssistantRole, tv, false, false) return } lastToolCall.Args = openAIToolMap @@ -880,7 +858,7 @@ func findCall(msg, toolCall string, tv *tview.TextView) { chatBody.Messages = append(chatBody.Messages, toolResponseMsg) logger.Debug("findCall: added tool error response", "role", toolResponseMsg.Role, "content_len", len(toolResponseMsg.Content), "message_count_after_add", len(chatBody.Messages)) // Trigger the assistant to continue processing with the error message - chatRound("", cfg.AssistantRole, tv, false, false, false) + chatRound("", cfg.AssistantRole, tv, false, false) return } // Update lastToolCall with parsed function call @@ -913,7 +891,7 @@ func findCall(msg, toolCall string, tv *tview.TextView) { lastToolCall.ID = "" // Trigger the assistant to continue processing with the new tool response // by calling chatRound with empty content to continue the assistant's response - chatRound("", cfg.AssistantRole, tv, false, false, false) + chatRound("", cfg.AssistantRole, tv, false, false) return } resp := callToolWithAgent(fc.Name, fc.Args) @@ -933,7 +911,7 @@ func findCall(msg, toolCall string, tv *tview.TextView) { lastToolCall.ID = "" // Trigger the assistant to continue processing with the new tool response // by calling chatRound with empty content to continue the assistant's response - chatRound("", cfg.AssistantRole, tv, false, false, false) + chatRound("", cfg.AssistantRole, tv, false, false) } func chatToTextSlice(showSys bool) []string { @@ -1057,18 +1035,15 @@ func refreshLocalModelsIfEmpty() { func summarizeAndStartNewChat() { if len(chatBody.Messages) == 0 { - notifyUser("info", "No chat history to summarize") + _ = notifyUser("info", "No chat history to summarize") return } - // Create a dummy TextView for the summary request (won't be displayed) - dummyTV := tview.NewTextView() - // Call chatRound with summaryMode true to generate summary - notifyUser("info", "Summarizing chat history...") - lastSummary = "" - chatRound("", cfg.UserRole, dummyTV, false, false, true) - summary := lastSummary + _ = notifyUser("info", "Summarizing chat history...") + // Call the summarize_chat tool via agent + summaryBytes := callToolWithAgent("summarize_chat", map[string]string{}) + summary := string(summaryBytes) if summary == "" { - notifyUser("error", "Failed to generate summary") + _ = notifyUser("error", "Failed to generate summary") return } // Start a new chat @@ -1087,7 +1062,7 @@ func summarizeAndStartNewChat() { if err := updateStorageChat(activeChatName, chatBody.Messages); err != nil { logger.Warn("failed to update storage after injecting summary", "error", err) } - notifyUser("info", "Chat summarized and new chat started with summary as tool response") + _ = notifyUser("info", "Chat summarized and new chat started with summary as tool response") } func init() { @@ -129,6 +129,7 @@ After that you are free to respond to the user. ` webSearchSysPrompt = `Summarize the web search results, extracting key information and presenting a concise answer. Provide sources and URLs where relevant.` readURLSysPrompt = `Extract and summarize the content from the webpage. Provide key information, main points, and any relevant details.` + summarySysPrompt = `Please provide a concise summary of the following conversation. Focus on key points, decisions, and actions. Provide only the summary, no additional commentary.` basicCard = &models.CharCard{ SysPrompt: basicSysMsg, FirstMsg: defaultFirstMsg, @@ -178,6 +179,8 @@ func registerWebAgents() { agent.Register("websearch", agent.NewWebAgentB(client, webSearchSysPrompt)) // Register read_url agent agent.Register("read_url", agent.NewWebAgentB(client, readURLSysPrompt)) + // Register summarize_chat agent + agent.Register("summarize_chat", agent.NewWebAgentB(client, summarySysPrompt)) }) } @@ -864,6 +867,15 @@ func isCommandAllowed(command string) bool { return allowedCommands[command] } +func summarizeChat(args map[string]string) []byte { + if len(chatBody.Messages) == 0 { + return []byte("No chat history to summarize.") + } + // Format chat history for the agent + chatText := chatToText(true) // include system and tool messages + return []byte(chatText) +} + type fnSig func(map[string]string) []byte var fnMap = map[string]fnSig{ @@ -884,6 +896,7 @@ var fnMap = map[string]fnSig{ "todo_read": todoRead, "todo_update": todoUpdate, "todo_delete": todoDelete, + "summarize_chat": summarizeChat, } // callToolWithAgent calls the tool and applies any registered agent. @@ -831,7 +831,7 @@ func init() { // there is no case where user msg is regenerated // lastRole := chatBody.Messages[len(chatBody.Messages)-1].Role textView.SetText(chatToText(cfg.ShowSys)) - go chatRound("", cfg.UserRole, textView, true, false, false) + go chatRound("", cfg.UserRole, textView, true, false) return nil } if event.Key() == tcell.KeyF3 && !botRespMode { @@ -1134,7 +1134,7 @@ func init() { // INFO: continue bot/text message // without new role lastRole := chatBody.Messages[len(chatBody.Messages)-1].Role - go chatRound("", lastRole, textView, false, true, false) + go chatRound("", lastRole, textView, false, true) return nil } if event.Key() == tcell.KeyCtrlQ { @@ -1294,7 +1294,7 @@ func init() { textView.ScrollToEnd() colorText() } - go chatRound(msgText, persona, textView, false, false, false) + go chatRound(msgText, persona, textView, false, false) // Also clear any image attachment after sending the message go func() { // Wait a short moment for the message to be processed, then clear the image attachment |
