diff options
| author | Grail Finder <wohilas@gmail.com> | 2026-02-04 11:22:17 +0300 |
|---|---|---|
| committer | Grail Finder <wohilas@gmail.com> | 2026-02-04 11:22:17 +0300 |
| commit | 79861e7c2bc6f2ed95309ca6e83577ddc4e2c63a (patch) | |
| tree | 5e60dc586b5db9783043488f1cfb06e4ad6d693e | |
| parent | e3965db3c7e7f5e3cdbf5d03ac06103c2709c0d8 (diff) | |
Enha: privateMessageResp with resume
| -rw-r--r-- | bot.go | 36 | ||||
| -rw-r--r-- | char-specific-context.md | 3 | ||||
| -rw-r--r-- | llm.go | 39 |
3 files changed, 41 insertions, 37 deletions
@@ -96,8 +96,10 @@ func parseKnownToTag(content string) []string { if list == "" { continue } - parts := strings.Split(list, ",") - for _, p := range parts { + strings.SplitSeq(list, ",") + // parts := strings.Split(list, ",") + // for _, p := range parts { + for p := range strings.SplitSeq(list, ",") { p = strings.TrimSpace(p) if p != "" { knownTo = append(knownTo, p) @@ -118,25 +120,17 @@ func processMessageTag(msg models.RoleMsg) models.RoleMsg { // If KnownTo already set, assume tag already processed (content cleaned). // However, we still check for new tags (maybe added later). knownTo := parseKnownToTag(msg.Content) - // logger.Info("processing tags", "msg", msg.Content, "known_to", knownTo) // If tag found, replace KnownTo with new list (merge with existing?) // For simplicity, if knownTo is not nil, replace. - if knownTo != nil { - msg.KnownTo = knownTo - // Only ensure sender role is in KnownTo if there was a tag - // This means the message is intended for specific characters - if msg.Role != "" { - senderAdded := false - for _, k := range msg.KnownTo { - if k == msg.Role { - senderAdded = true - break - } - } - if !senderAdded { - msg.KnownTo = append(msg.KnownTo, msg.Role) - } - } + if knownTo == nil { + return msg + } + msg.KnownTo = knownTo + if msg.Role == "" { + return msg + } + if !slices.Contains(msg.KnownTo, msg.Role) { + msg.KnownTo = append(msg.KnownTo, msg.Role) } return msg } @@ -781,9 +775,6 @@ func chatWatcher(ctx context.Context) { } func chatRound(r *models.ChatRoundReq) error { - // chunkChan := make(chan string, 10) - // openAIToolChan := make(chan string, 10) - // streamDone := make(chan bool, 1) botRespMode = true botPersona := cfg.AssistantRole if cfg.WriteNextMsgAsCompletionAgent != "" { @@ -1350,6 +1341,7 @@ func triggerPrivateMessageResponses(msg models.RoleMsg) { crr := &models.ChatRoundReq{ UserMsg: triggerMsg, Role: recipient, + Resume: true, } chatRoundChan <- crr } diff --git a/char-specific-context.md b/char-specific-context.md index 423572b..f06fd75 100644 --- a/char-specific-context.md +++ b/char-specific-context.md @@ -130,6 +130,9 @@ Card example: Character‑specific context relies on the `/completion` endpoint (or other completion‑style endpoints) where the LLM is presented with a raw text prompt containing the entire filtered history. It does **not** work with OpenAI‑style `/v1/chat/completions` endpoints, because those endpoints enforce a fixed role set (`user`/`assistant`/`system`) and strip custom role names and metadata. +### TTS +Although text message might be hidden from user character. If TTS is enabled it will be read. + ### Tag Parsing - The tag is case‑sensitive. @@ -138,7 +138,8 @@ func (lcp LCPCompletion) FormMsg(msg, role string, resume bool) (io.Reader, erro if localImageAttachmentPath != "" { imageURL, err := models.CreateImageURLFromPath(localImageAttachmentPath) if err != nil { - logger.Error("failed to create image URL from path for completion", "error", err, "path", localImageAttachmentPath) + logger.Error("failed to create image URL from path for completion", + "error", err, "path", localImageAttachmentPath) return nil, err } // Extract base64 part from data URL (e.g., "data:image/jpeg;base64,...") @@ -166,15 +167,16 @@ func (lcp LCPCompletion) FormMsg(msg, role string, resume bool) (io.Reader, erro logger.Error("failed to form a rag msg", "error", err) return nil, err } - logger.Debug("RAG response received", "response_len", len(ragResp), "response_preview", ragResp[:min(len(ragResp), 100)]) + logger.Debug("RAG response received", "response_len", len(ragResp), + "response_preview", ragResp[:min(len(ragResp), 100)]) // Use system role for RAG context to avoid conflicts with tool usage ragMsg := models.RoleMsg{Role: "system", Content: RAGMsg + ragResp} 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() { - // add to chat body chatBody.Messages = append(chatBody.Messages, models.RoleMsg{Role: cfg.ToolRole, Content: toolSysMsg}) } filteredMessages, botPersona := filterMessagesForCurrentCharacter(chatBody.Messages) @@ -310,7 +312,8 @@ func (op LCPChat) FormMsg(msg, role string, resume bool) (io.Reader, error) { } newMsg = processMessageTag(newMsg) chatBody.Messages = append(chatBody.Messages, newMsg) - logger.Debug("LCPChat FormMsg: added message to chatBody", "role", newMsg.Role, "content_len", len(newMsg.Content), "message_count_after_add", len(chatBody.Messages)) + 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 @@ -322,11 +325,13 @@ func (op LCPChat) FormMsg(msg, role string, resume bool) (io.Reader, error) { logger.Error("LCPChat: failed to form a rag msg", "error", err) return nil, err } - logger.Debug("LCPChat: RAG response received", "response_len", len(ragResp), "response_preview", ragResp[:min(len(ragResp), 100)]) + logger.Debug("LCPChat: RAG response received", + "response_len", len(ragResp), "response_preview", ragResp[:min(len(ragResp), 100)]) // Use system role for RAG context to avoid conflicts with tool usage ragMsg := models.RoleMsg{Role: "system", Content: RAGMsg + ragResp} chatBody.Messages = append(chatBody.Messages, ragMsg) - 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)) + 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) @@ -409,15 +414,16 @@ func (ds DeepSeekerCompletion) FormMsg(msg, role string, resume bool) (io.Reader logger.Error("DeepSeekerCompletion: failed to form a rag msg", "error", err) return nil, err } - logger.Debug("DeepSeekerCompletion: RAG response received", "response_len", len(ragResp), "response_preview", ragResp[:min(len(ragResp), 100)]) + logger.Debug("DeepSeekerCompletion: RAG response received", + "response_len", len(ragResp), "response_preview", ragResp[:min(len(ragResp), 100)]) // Use system role for RAG context to avoid conflicts with tool usage ragMsg := models.RoleMsg{Role: "system", Content: RAGMsg + ragResp} 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() { - // add to chat body chatBody.Messages = append(chatBody.Messages, models.RoleMsg{Role: cfg.ToolRole, Content: toolSysMsg}) } filteredMessages, botPersona := filterMessagesForCurrentCharacter(chatBody.Messages) @@ -494,7 +500,8 @@ func (ds DeepSeekerChat) FormMsg(msg, role string, resume bool) (io.Reader, erro logger.Error("failed to form a rag msg", "error", err) return nil, err } - logger.Debug("RAG response received", "response_len", len(ragResp), "response_preview", ragResp[:min(len(ragResp), 100)]) + logger.Debug("RAG response received", "response_len", len(ragResp), + "response_preview", ragResp[:min(len(ragResp), 100)]) // Use system role for RAG context to avoid conflicts with tool usage ragMsg := models.RoleMsg{Role: "system", Content: RAGMsg + ragResp} chatBody.Messages = append(chatBody.Messages, ragMsg) @@ -571,15 +578,16 @@ func (or OpenRouterCompletion) FormMsg(msg, role string, resume bool) (io.Reader logger.Error("failed to form a rag msg", "error", err) return nil, err } - logger.Debug("RAG response received", "response_len", len(ragResp), "response_preview", ragResp[:min(len(ragResp), 100)]) + logger.Debug("RAG response received", "response_len", + len(ragResp), "response_preview", ragResp[:min(len(ragResp), 100)]) // Use system role for RAG context to avoid conflicts with tool usage ragMsg := models.RoleMsg{Role: "system", Content: RAGMsg + ragResp} 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() { - // add to chat body chatBody.Messages = append(chatBody.Messages, models.RoleMsg{Role: cfg.ToolRole, Content: toolSysMsg}) } filteredMessages, botPersona := filterMessagesForCurrentCharacter(chatBody.Messages) @@ -596,11 +604,11 @@ func (or OpenRouterCompletion) FormMsg(msg, role string, resume bool) (io.Reader if cfg.ThinkUse && !cfg.ToolUse { prompt += "<think>" } - ss := chatBody.MakeStopSliceExcluding(botPersona, listChatRoles()) + stopSlice := chatBody.MakeStopSliceExcluding(botPersona, listChatRoles()) logger.Debug("checking prompt for /completion", "tool_use", cfg.ToolUse, - "msg", msg, "resume", resume, "prompt", prompt, "stop_strings", ss) + "msg", msg, "resume", resume, "prompt", prompt, "stop_strings", stopSlice) payload := models.NewOpenRouterCompletionReq(chatBody.Model, prompt, - defaultLCPProps, ss) + defaultLCPProps, stopSlice) data, err := json.Marshal(payload) if err != nil { logger.Error("failed to form a msg", "error", err) @@ -687,7 +695,8 @@ func (or OpenRouterChat) FormMsg(msg, role string, resume bool) (io.Reader, erro logger.Error("failed to form a rag msg", "error", err) return nil, err } - logger.Debug("RAG response received", "response_len", len(ragResp), "response_preview", ragResp[:min(len(ragResp), 100)]) + logger.Debug("RAG response received", "response_len", len(ragResp), + "response_preview", ragResp[:min(len(ragResp), 100)]) // Use system role for RAG context to avoid conflicts with tool usage ragMsg := models.RoleMsg{Role: "system", Content: RAGMsg + ragResp} chatBody.Messages = append(chatBody.Messages, ragMsg) |
