Enha: extract first valid recipient from knownto

This commit is contained in:
Grail Finder
2026-02-08 21:50:03 +03:00
parent 93284312cf
commit 1bf9e6eef7
2 changed files with 128 additions and 126 deletions

33
bot.go
View File

@@ -1305,15 +1305,17 @@ func init() {
go chatWatcher(ctx)
}
// triggerPrivateMessageResponses checks if a message was sent privately to specific characters
// and triggers those non-user characters to respond
func triggerPrivateMessageResponses(msg *models.RoleMsg) {
func getValidKnowToRecipient(msg *models.RoleMsg) (string, bool) {
if cfg == nil || !cfg.CharSpecificContextEnabled {
return
return "", false
}
userCharacter := cfg.UserRole
if cfg.WriteNextMsgAs != "" {
userCharacter = cfg.WriteNextMsgAs
// case where all roles are in the tag => public message
cr := listChatRoles()
slices.Sort(cr)
slices.Sort(msg.KnownTo)
if slices.Equal(cr, msg.KnownTo) {
logger.Info("got msg with tag mentioning every role")
return "", false
}
// Check each character in the KnownTo list
for _, recipient := range msg.KnownTo {
@@ -1323,8 +1325,20 @@ func triggerPrivateMessageResponses(msg *models.RoleMsg) {
}
// Skip if this is the user character (user handles their own turn)
// If user is in KnownTo, stop processing - it's the user's turn
if recipient == cfg.UserRole || recipient == userCharacter {
return // user in known_to => user's turn
if recipient == cfg.UserRole || recipient == cfg.WriteNextMsgAs {
return "", false
}
return recipient, true
}
return "", false
}
// triggerPrivateMessageResponses checks if a message was sent privately to specific characters
// and triggers those non-user characters to respond
func triggerPrivateMessageResponses(msg *models.RoleMsg) {
recipient, ok := getValidKnowToRecipient(msg)
if !ok || recipient == "" {
return
}
// Trigger the recipient character to respond
triggerMsg := recipient + ":\n"
@@ -1339,4 +1353,3 @@ func triggerPrivateMessageResponses(msg *models.RoleMsg) {
fmt.Fprint(textView, "[-:-:-]\n")
chatRoundChan <- crr
}
}

35
llm.go
View File

@@ -59,16 +59,18 @@ func ClearImageAttachment() {
// filterMessagesForCurrentCharacter filters messages based on char-specific context.
// Returns filtered messages and the bot persona role (target character).
func filterMessagesForCurrentCharacter(messages []models.RoleMsg) ([]models.RoleMsg, string) {
if cfg == nil || !cfg.CharSpecificContextEnabled {
botPersona := cfg.AssistantRole
if cfg.WriteNextMsgAsCompletionAgent != "" {
botPersona = cfg.WriteNextMsgAsCompletionAgent
}
if cfg == nil || !cfg.CharSpecificContextEnabled {
return messages, botPersona
}
botPersona := cfg.AssistantRole
if cfg.WriteNextMsgAsCompletionAgent != "" {
botPersona = cfg.WriteNextMsgAsCompletionAgent
// get last message (written by user) and checck if it has a tag
lm := messages[len(messages)-1]
recipient, ok := getValidKnowToRecipient(&lm)
if ok && recipient != "" {
botPersona = recipient
}
filtered := filterMessagesForCharacter(messages, botPersona)
return filtered, botPersona
@@ -162,9 +164,8 @@ func (lcp LCPCompletion) FormMsg(msg, role string, resume bool) (io.Reader, erro
newMsg = *processMessageTag(&newMsg)
chatBody.Messages = append(chatBody.Messages, newMsg)
}
if !resume {
// if rag - add as system message to avoid conflicts with tool usage
if cfg.RAGEnabled {
if !resume && cfg.RAGEnabled {
um := chatBody.Messages[len(chatBody.Messages)-1].Content
logger.Debug("RAG is enabled, preparing RAG context", "user_message", um)
ragResp, err := chatRagUse(um)
@@ -179,7 +180,6 @@ func (lcp LCPCompletion) FormMsg(msg, role string, resume bool) (io.Reader, erro
chatBody.Messages = append(chatBody.Messages, ragMsg)
logger.Debug("RAG message added to chat body", "message_count", len(chatBody.Messages))
}
}
// sending description of the tools and how to use them
if cfg.ToolUse && !resume && role == cfg.UserRole && !containsToolSysMsg() {
chatBody.Messages = append(chatBody.Messages, models.RoleMsg{Role: cfg.ToolRole, Content: toolSysMsg})
@@ -324,9 +324,8 @@ func (op LCPChat) FormMsg(msg, role string, resume bool) (io.Reader, error) {
logger.Debug("LCPChat FormMsg: added message to chatBody", "role", newMsg.Role,
"content_len", len(newMsg.Content), "message_count_after_add", len(chatBody.Messages))
}
if !resume {
// if rag - add as system message to avoid conflicts with tool usage
if cfg.RAGEnabled {
if !resume && cfg.RAGEnabled {
um := chatBody.Messages[len(chatBody.Messages)-1].Content
logger.Debug("LCPChat: RAG is enabled, preparing RAG context", "user_message", um)
ragResp, err := chatRagUse(um)
@@ -342,7 +341,6 @@ func (op LCPChat) FormMsg(msg, role string, resume bool) (io.Reader, error) {
logger.Debug("LCPChat: RAG message added to chat body", "role", ragMsg.Role,
"rag_content_len", len(ragMsg.Content), "message_count_after_rag", len(chatBody.Messages))
}
}
filteredMessages, botPersona := filterMessagesForCurrentCharacter(chatBody.Messages)
// openai /v1/chat does not support custom roles; needs to be user, assistant, system
// Add persona suffix to the last user message to indicate who the assistant should reply as
@@ -416,10 +414,8 @@ func (ds DeepSeekerCompletion) FormMsg(msg, role string, resume bool) (io.Reader
newMsg = *processMessageTag(&newMsg)
chatBody.Messages = append(chatBody.Messages, newMsg)
}
if !resume {
// if rag - add as system message to avoid conflicts with tool usage
// TODO: perhaps RAG should be a func/tool call instead?
if cfg.RAGEnabled {
if !resume && cfg.RAGEnabled {
um := chatBody.Messages[len(chatBody.Messages)-1].Content
logger.Debug("DeepSeekerCompletion: RAG is enabled, preparing RAG context", "user_message", um)
ragResp, err := chatRagUse(um)
@@ -434,7 +430,6 @@ func (ds DeepSeekerCompletion) FormMsg(msg, role string, resume bool) (io.Reader
chatBody.Messages = append(chatBody.Messages, ragMsg)
logger.Debug("DeepSeekerCompletion: RAG message added to chat body", "message_count", len(chatBody.Messages))
}
}
// sending description of the tools and how to use them
if cfg.ToolUse && !resume && role == cfg.UserRole && !containsToolSysMsg() {
chatBody.Messages = append(chatBody.Messages, models.RoleMsg{Role: cfg.ToolRole, Content: toolSysMsg})
@@ -507,9 +502,8 @@ func (ds DeepSeekerChat) FormMsg(msg, role string, resume bool) (io.Reader, erro
newMsg = *processMessageTag(&newMsg)
chatBody.Messages = append(chatBody.Messages, newMsg)
}
if !resume {
// if rag - add as system message to avoid conflicts with tool usage
if cfg.RAGEnabled {
if !resume && cfg.RAGEnabled {
um := chatBody.Messages[len(chatBody.Messages)-1].Content
logger.Debug("RAG is enabled, preparing RAG context", "user_message", um)
ragResp, err := chatRagUse(um)
@@ -524,7 +518,6 @@ func (ds DeepSeekerChat) FormMsg(msg, role string, resume bool) (io.Reader, erro
chatBody.Messages = append(chatBody.Messages, ragMsg)
logger.Debug("RAG message added to chat body", "message_count", len(chatBody.Messages))
}
}
// Create copy of chat body with standardized user role
filteredMessages, botPersona := filterMessagesForCurrentCharacter(chatBody.Messages)
// Add persona suffix to the last user message to indicate who the assistant should reply as
@@ -589,9 +582,8 @@ func (or OpenRouterCompletion) FormMsg(msg, role string, resume bool) (io.Reader
newMsg = *processMessageTag(&newMsg)
chatBody.Messages = append(chatBody.Messages, newMsg)
}
if !resume {
// if rag - add as system message to avoid conflicts with tool usage
if cfg.RAGEnabled {
if !resume && cfg.RAGEnabled {
um := chatBody.Messages[len(chatBody.Messages)-1].Content
logger.Debug("RAG is enabled, preparing RAG context", "user_message", um)
ragResp, err := chatRagUse(um)
@@ -606,7 +598,6 @@ func (or OpenRouterCompletion) FormMsg(msg, role string, resume bool) (io.Reader
chatBody.Messages = append(chatBody.Messages, ragMsg)
logger.Debug("RAG message added to chat body", "message_count", len(chatBody.Messages))
}
}
// sending description of the tools and how to use them
if cfg.ToolUse && !resume && role == cfg.UserRole && !containsToolSysMsg() {
chatBody.Messages = append(chatBody.Messages, models.RoleMsg{Role: cfg.ToolRole, Content: toolSysMsg})
@@ -710,9 +701,8 @@ func (or OpenRouterChat) FormMsg(msg, role string, resume bool) (io.Reader, erro
newMsg = *processMessageTag(&newMsg)
chatBody.Messages = append(chatBody.Messages, newMsg)
}
if !resume {
// if rag - add as system message to avoid conflicts with tool usage
if cfg.RAGEnabled {
if !resume && cfg.RAGEnabled {
um := chatBody.Messages[len(chatBody.Messages)-1].Content
logger.Debug("RAG is enabled, preparing RAG context", "user_message", um)
ragResp, err := chatRagUse(um)
@@ -727,7 +717,6 @@ func (or OpenRouterChat) FormMsg(msg, role string, resume bool) (io.Reader, erro
chatBody.Messages = append(chatBody.Messages, ragMsg)
logger.Debug("RAG message added to chat body", "message_count", len(chatBody.Messages))
}
}
// Create copy of chat body with standardized user role
filteredMessages, botPersona := filterMessagesForCurrentCharacter(chatBody.Messages)
// Add persona suffix to the last user message to indicate who the assistant should reply as