mirror of
https://github.com/tiennm99/goclaw.git
synced 2026-10-13 22:15:47 +00:00
fix: Telegram @mention linking + conditional media read prompts
- Convert @mentions to <a href="https://t.me/username"> in HTML formatter (Telegram Bot API does NOT auto-link @username in parse_mode: HTML) - Protect @mentions from italic regex mangling underscored usernames - Change read_image/read_audio/read_video system prompt from "REQUIRED" to conditional — model only reads media when relevant to user's question - Annotate history media tags so model distinguishes group context images from current-turn images
This commit is contained in:
1 parent
e7afa83245
commit
216b8abac6
3 files changed
+28
-6
No files matched your search
@@ -98,9 +98,9 @@ var coreToolSummaries = map[string]string{
|
||||
"session_status": "Show session status (model, tokens, compaction count)",
|
||||
"sessions_history": "Fetch message history for a session",
|
||||
"sessions_send": "Send a message into another session",
|
||||
"read_image": "REQUIRED when you see <media:image> tags — call this tool with the path attribute to analyze the image. You CAN see images through this tool. Never say you cannot see images",
|
||||
"read_audio": "REQUIRED when you see <media:audio> tags — call this tool to transcribe or analyze audio content",
|
||||
"read_video": "REQUIRED when you see <media:video> tags — call this tool to analyze video content",
|
||||
"read_image": "Analyze images when the user asks about them or when understanding the image is needed to answer. Call with the path attribute from <media:image> tags. You CAN see images through this tool. Never say you cannot see images",
|
||||
"read_audio": "Analyze audio when the user asks about it or references audio content. Call with the media_id from <media:audio> tags. You CAN hear audio through this tool",
|
||||
"read_video": "Analyze video when the user asks about it or references video content. Call with the media_id from <media:video> tags. You CAN see video through this tool",
|
||||
"create_video": "Generate videos from text descriptions using AI",
|
||||
"read_document": "Analyze documents (PDF, DOCX, etc.) attached to the conversation. Call this when you see <media:document> tags. If this tool fails, use a relevant skill instead (e.g. pdf skill with exec tool). The path attribute in <media:document path=\"...\"> is a directly accessible file in your workspace — use it directly, no need to copy",
|
||||
"create_image": "Generate images from text descriptions using AI",
|
||||
@@ -389,9 +389,9 @@ func buildToolingSection(toolNames []string, hasSandbox bool, shellDenyGroups ma
|
||||
"When users send images, videos, audio, or documents, you see tags like:",
|
||||
` <media:image id="..." path="...">`,
|
||||
` <media:video id="...">, <media:audio id="...">, <media:document path="...">`,
|
||||
"You MUST use the corresponding read_* tool (with the path or media_id) to analyze them.",
|
||||
"Use the corresponding read_* tool (with the path or media_id) to analyze them when the user asks about them or when understanding the media is needed to answer.",
|
||||
"You have full vision/audio/video capabilities through these tools.",
|
||||
"NEVER say you cannot see images or files — always use the tools.",
|
||||
"NEVER say you cannot see images or files — always use the tools when relevant.",
|
||||
)
|
||||
}
|
||||
|
||||
|
||||
@@ -77,6 +77,21 @@ func markdownToTelegramHTML(text string) string {
|
||||
text = regexp.MustCompile(`\*\*(.+?)\*\*`).ReplaceAllString(text, "<b>$1</b>")
|
||||
text = regexp.MustCompile(`__(.+?)__`).ReplaceAllString(text, "<b>$1</b>")
|
||||
|
||||
// Protect @mentions from italic conversion and convert to clickable Telegram links.
|
||||
// In HTML parse_mode, Telegram does NOT auto-link @username — we must use <a> tags.
|
||||
// Uses (^|\W) prefix to avoid matching emails like user@domain.com.
|
||||
var mentionPlaceholders []string
|
||||
reMention := regexp.MustCompile(`(^|\W)(@\w+)`)
|
||||
text = reMention.ReplaceAllStringFunc(text, func(s string) string {
|
||||
match := reMention.FindStringSubmatch(s)
|
||||
if len(match) < 3 {
|
||||
return s
|
||||
}
|
||||
idx := len(mentionPlaceholders)
|
||||
mentionPlaceholders = append(mentionPlaceholders, match[2])
|
||||
return match[1] + fmt.Sprintf("\x00MN%d\x00", idx)
|
||||
})
|
||||
|
||||
// Italic
|
||||
reItalic := regexp.MustCompile(`_([^_]+)_`)
|
||||
text = reItalic.ReplaceAllStringFunc(text, func(s string) string {
|
||||
@@ -90,6 +105,13 @@ func markdownToTelegramHTML(text string) string {
|
||||
// Strikethrough
|
||||
text = regexp.MustCompile(`~~(.+?)~~`).ReplaceAllString(text, "<s>$1</s>")
|
||||
|
||||
// Restore @mentions as clickable Telegram links
|
||||
for i, mention := range mentionPlaceholders {
|
||||
username := strings.TrimPrefix(mention, "@")
|
||||
linked := fmt.Sprintf(`<a href="https://t.me/%s">%s</a>`, username, mention)
|
||||
text = strings.ReplaceAll(text, fmt.Sprintf("\x00MN%d\x00", i), linked)
|
||||
}
|
||||
|
||||
// List items
|
||||
text = regexp.MustCompile(`(?m)^[-*]\s+`).ReplaceAllString(text, "• ")
|
||||
|
||||
|
||||
@@ -482,7 +482,7 @@ func (c *Channel) handleMessage(ctx context.Context, update telego.Update) {
|
||||
}
|
||||
if len(histMedia) > 0 {
|
||||
histTags := buildMediaTags(histMedia)
|
||||
annotated = histTags + "\n\n" + annotated
|
||||
annotated = "[Media from recent group messages — only analyze if user asks about them]\n" + histTags + "\n[/Media]\n\n" + annotated
|
||||
}
|
||||
for _, e := range histErrors {
|
||||
slog.Warn("telegram: history media download failed",
|
||||
|
||||
Reference in new issue
Block a user