fix: 消息日志增强 + 历史消息抑制 + SSE实时追踪 + 群聊上下文优化

- 日志:收/发消息均显示群名称,管理员显示真实QQ昵称而非"开拓者"
- 历史消息:服务重启后NapCat回放的历史消息不再触发回复,静默注入上下文
- 消息时间戳:转发给AI时附带【消息时间: HH:MM:SS (XmXs前)】标记
- ♪ 分割符:QQ消息支持♪作为句子断点
- AI-Core SSE端点:全链路追踪实时推送,ethend不再5秒轮询
- 群聊上下文:AI-Core明确被告知消息来自群聊,以实际发送者为主语

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
This commit is contained in:
2026-05-31 11:49:36 +08:00
parent 677385ec17
commit 3ad728406e
13 changed files with 587 additions and 156 deletions
@@ -576,7 +576,7 @@ func (t *Thinker) performPlatformObservation() {
log.Printf("[后台思考] 平台观察:%d 个频道有记忆数据,调用中间会话生成摘要...", len(channelSummaries))
systemPrompt := "你是昔涟的后台观察助手。以下是各聊天平台频道最近的观察摘要。\n请生成简洁报告:\n1. 各频道近期讨论主题(每频道1-2句)\n2. 是否有需要开拓者关注的重要/紧急事项\n3. 整体氛围评估\n不要直接对开拓者说话,这是给昔涟参考的幕后报告。\n输出为JSON格式:{\"summary\": \"报告内容\", \"needs_attention\": true/false}"
systemPrompt := "你是昔涟的后台观察助手。以下是各聊天平台频道最近的观察摘要。\n请生成简洁报告:\n1. 各频道近期讨论主题(每频道1-2句)\n2. 是否有需要关注的重要/紧急事项\n3. 整体氛围评估\n注意:这些记忆可能来自不同的群聊成员(不只是开拓者),请以实际发言者为主语描述。不要直接对开拓者说话,这是给昔涟参考的幕后报告。\n输出为JSON格式:{\"summary\": \"报告内容\", \"needs_attention\": true/false}"
userPrompt := strings.Join(channelSummaries, "\n\n")
@@ -1099,12 +1099,12 @@ func (t *Thinker) buildThinkingUserPrompt(
switch triggerReason {
case "post_chat":
sb.WriteString("开拓者刚和你聊完天。你想自然地在心里回味一下刚才的对话……\n")
sb.WriteString("刚有人和你聊完天。你想自然地在心里回味一下刚才的对话……\n")
case "silence":
t.mu.Lock()
silenceDuration := time.Since(t.lastUserMessage)
t.mu.Unlock()
sb.WriteString(fmt.Sprintf("开拓者已经大约 %s 没有说话了。你有点想知道在做什么……\n",
sb.WriteString(fmt.Sprintf("已经大约 %s 没有说话了。你有点想知道大家在做什么……\n",
formatDurationHuman(silenceDuration)))
default:
sb.WriteString("现在是你的自由思考时间。\n")
@@ -1117,7 +1117,7 @@ func (t *Thinker) buildThinkingUserPrompt(
msgCount := 0
for _, msg := range convHistory {
if msg.Role == model.RoleUser || msg.Role == model.RoleAssistant {
roleLabel := "开拓者"
roleLabel := "用户"
if msg.Role == model.RoleAssistant {
roleLabel = "昔涟"
}
@@ -1185,7 +1185,7 @@ func (t *Thinker) buildThinkingUserPrompt(
// 平台观察摘要 (中间会话产生的报告)
if platformObservation != "" {
sb.WriteString("\n\n【平台频道观察报告(中间会话生成,供参考)】\n")
sb.WriteString("\n\n【平台频道观察报告(中间会话生成,可能包含多位群聊成员的信息)】\n")
sb.WriteString(platformObservation)
sb.WriteString("\n")
}
@@ -1193,9 +1193,9 @@ func (t *Thinker) buildThinkingUserPrompt(
// 结尾引导
sb.WriteString("\n---\n现在请写下你的私人反思。")
sb.WriteString("\n记住:这是日记,用第三人称或自言自语的方式。")
sb.WriteString("\n⚠️ 如果开拓者正在休息/睡觉/忙碌——不要输出【主动消息】指令行。你可以在心里想,但不要去打扰。")
sb.WriteString("\n只有在你确认现在是醒着、有空、且真的需要关心时,才输出一行【主动消息】+ 你要发给他的话。")
sb.WriteString("\n❗【主动消息】标记必须独占一行开头,后面紧跟你要对开拓者说的话(用\"你\"称呼),语气自然像主动找聊天。不要在反思正文中提及\"主动消息\"这个词——如果需要表达这个意思但又不打算发消息,用别的词代替。")
sb.WriteString("\n⚠️ 如果有人正在休息/睡觉/忙碌——不要输出【主动消息】指令行。你可以在心里想,但不要去打扰。")
sb.WriteString("\n只有在你确认对方现在是醒着、有空、且真的需要关心时,才输出一行【主动消息】+ 你要发给他的话。")
sb.WriteString("\n❗【主动消息】标记必须独占一行开头,后面紧跟你要说的话(用\"你\"称呼),语气自然像主动找对方聊天。不要在反思正文中提及\"主动消息\"这个词——如果需要表达这个意思但又不打算发消息,用别的词代替。")
return sb.String()
}