fix: 回退thinker.go到6490c34稳定版

This commit is contained in:
2026-06-28 16:58:55 +08:00
parent 32160d9453
commit 76e648aac3
+33 -65
View File
@@ -292,31 +292,27 @@ func timePeriod(now time.Time) (string, string) {
// SetMessagePusher 设置主动消息推送回调 // SetMessagePusher 设置主动消息推送回调
// SetScheduleLoader sets the dynamic schedule loader for interval calculation. // SetScheduleLoader sets the dynamic schedule loader for interval calculation.
func (t *Thinker) SetScheduleLoader(loader *ScheduleLoader) { func (t *Thinker) SetScheduleLoader(loader *ScheduleLoader) {
if !t.muLock() { t.muLock()
return
defer t.muUnlock() defer t.muUnlock()
t.scheduleLoader = loader t.scheduleLoader = loader
} }
func (t *Thinker) SetMessagePusher(pusher func(string, string, string)) { func (t *Thinker) SetMessagePusher(pusher func(string, string, string)) {
if !t.muLock() { t.muLock()
return
defer t.muUnlock() defer t.muUnlock()
t.messagePusher = pusher t.messagePusher = pusher
} }
// SetPlatformMessagePusher sets the callback for pushing proactive messages to platform adapters (OBv11, etc.). // SetPlatformMessagePusher sets the callback for pushing proactive messages to platform adapters (OBv11, etc.).
func (t *Thinker) SetPlatformMessagePusher(pusher func(ProactiveTarget, string)) { func (t *Thinker) SetPlatformMessagePusher(pusher func(ProactiveTarget, string)) {
if !t.muLock() { t.muLock()
return
defer t.muUnlock() defer t.muUnlock()
t.platformMessagePusher = pusher t.platformMessagePusher = pusher
} }
// SetBotUID sets the bot's own platform UID (e.g., OBv11 account). // SetBotUID sets the bot's own platform UID (e.g., OBv11 account).
func (t *Thinker) SetBotUID(platform, uid string) { func (t *Thinker) SetBotUID(platform, uid string) {
if !t.muLock() { t.muLock()
return
defer t.muUnlock() defer t.muUnlock()
if t.botUIDs == nil { if t.botUIDs == nil {
t.botUIDs = make(map[string]string) t.botUIDs = make(map[string]string)
@@ -328,8 +324,7 @@ func (t *Thinker) SetBotUID(platform, uid string) {
// AddOrUpdatePlatformChannel adds or updates a platform channel with resolved display name. // AddOrUpdatePlatformChannel adds or updates a platform channel with resolved display name.
func (t *Thinker) AddOrUpdatePlatformChannel(platform, channelType, channelID, channelName, adapterID, adapterName string) { func (t *Thinker) AddOrUpdatePlatformChannel(platform, channelType, channelID, channelName, adapterID, adapterName string) {
if !t.muLock() { t.muLock()
return
defer t.muUnlock() defer t.muUnlock()
for i, ch := range t.platformChannels { for i, ch := range t.platformChannels {
@@ -359,8 +354,7 @@ func (t *Thinker) AddOrUpdatePlatformChannel(platform, channelType, channelID, c
// SetEmotionTracker sets the emotion tracker. // SetEmotionTracker sets the emotion tracker.
func (t *Thinker) SetEmotionTracker(et *persona.EmotionTracker) { func (t *Thinker) SetEmotionTracker(et *persona.EmotionTracker) {
if !t.muLock() { t.muLock()
return
defer t.muUnlock() defer t.muUnlock()
t.emotionTracker = et t.emotionTracker = et
} }
@@ -368,8 +362,7 @@ func (t *Thinker) SetEmotionTracker(et *persona.EmotionTracker) {
// UpdatePresence updates the user online status. // UpdatePresence updates the user online status.
// Called by the ai-core presence endpoint when gateway detects connect/disconnect. // Called by the ai-core presence endpoint when gateway detects connect/disconnect.
func (t *Thinker) UpdatePresence(online bool, sessionID string) { func (t *Thinker) UpdatePresence(online bool, sessionID string) {
if !t.muLock() { t.muLock()
return
defer t.muUnlock() defer t.muUnlock()
wasOffline := !t.isUserOnline() wasOffline := !t.isUserOnline()
t.setUserOnline(online) t.setUserOnline(online)
@@ -397,8 +390,7 @@ func (t *Thinker) UpdatePresence(online bool, sessionID string) {
// TriggerReminderMessage pushes a reminder message generated by LLM to the user. // TriggerReminderMessage pushes a reminder message generated by LLM to the user.
// Called by the internal reminder-trigger endpoint when a reminder fires. // Called by the internal reminder-trigger endpoint when a reminder fires.
func (t *Thinker) TriggerReminderMessage(userID, sessionID, message string) { func (t *Thinker) TriggerReminderMessage(userID, sessionID, message string) {
if !t.muLock() { t.muLock()
return
defer t.muUnlock() defer t.muUnlock()
pusher := t.messagePusher pusher := t.messagePusher
pushSessionID := sessionID pushSessionID := sessionID
@@ -418,8 +410,7 @@ func (t *Thinker) TriggerReminderMessage(userID, sessionID, message string) {
// PushPlatformMessage pushes a message to a platform channel via the platform pusher. // PushPlatformMessage pushes a message to a platform channel via the platform pusher.
func (t *Thinker) PushPlatformMessage(target ProactiveTarget, message string) { func (t *Thinker) PushPlatformMessage(target ProactiveTarget, message string) {
if !t.muLock() { t.muLock()
return
defer t.muUnlock() defer t.muUnlock()
pusher := t.platformMessagePusher pusher := t.platformMessagePusher
@@ -433,8 +424,7 @@ func (t *Thinker) PushPlatformMessage(target ProactiveTarget, message string) {
// IsUserRecentlyActive returns true if the user has been active within the given duration. // IsUserRecentlyActive returns true if the user has been active within the given duration.
func (t *Thinker) IsUserRecentlyActive(d time.Duration) bool { func (t *Thinker) IsUserRecentlyActive(d time.Duration) bool {
if !t.muLock() { t.muLock()
return
defer t.muUnlock() defer t.muUnlock()
return time.Since(t.lastUserTime()) < d return time.Since(t.lastUserTime()) < d
} }
@@ -521,7 +511,7 @@ func NewThinker(
lightThinkEnabled: cfg.LightThinkEnabled, lightThinkEnabled: cfg.LightThinkEnabled,
lightThinkInterval: cfg.LightThinkInterval, lightThinkInterval: cfg.LightThinkInterval,
silenceTimeout: cfg.SilenceTimeout, silenceTimeout: cfg.SilenceTimeout,
proactiveMsgMinGap: getEnvDuration("PROACTIVE_MSG_MIN_GAP_SEC", 60), proactiveMsgMinGap: getEnvDuration("PROACTIVE_MSG_MIN_GAP_SEC", 300),
postChatDelay: cfg.PostChatDelay, postChatDelay: cfg.PostChatDelay,
minThinkGap: cfg.MinThinkGap, minThinkGap: cfg.MinThinkGap,
offlineThinkGap: cfg.OfflineThinkGap, offlineThinkGap: cfg.OfflineThinkGap,
@@ -567,8 +557,7 @@ func (t *Thinker) restoreContext() {
} }
} }
if !latest.IsZero() && time.Since(latest) < 24*time.Hour { if !latest.IsZero() && time.Since(latest) < 24*time.Hour {
if !t.muLock() { t.muLock()
return
defer t.muUnlock() defer t.muUnlock()
t.lastUserMessage = latest t.lastUserMessage = latest
t.setLastUser(latest) t.setLastUser(latest)
@@ -683,8 +672,7 @@ func (t *Thinker) TriggerPostChatThink() {
return return
} }
if !t.muLock() { t.muLock()
return
defer t.muUnlock() defer t.muUnlock()
canThink := time.Since(t.lastThinkTimeAtomic()) >= t.minThinkGap canThink := time.Since(t.lastThinkTimeAtomic()) >= t.minThinkGap
@@ -754,8 +742,7 @@ func (t *Thinker) resetSilenceTimer() {
return return
case <-t.silenceTimer.C: case <-t.silenceTimer.C:
// 再次检查:用户是否真的沉默了足够久 // 再次检查:用户是否真的沉默了足够久
if !t.muLock() { t.muLock()
return
defer t.muUnlock() defer t.muUnlock()
silenceDuration := time.Since(t.lastUserTime()) silenceDuration := time.Since(t.lastUserTime())
canThink := time.Since(t.lastThinkTimeAtomic()) >= t.minThinkGap canThink := time.Since(t.lastThinkTimeAtomic()) >= t.minThinkGap
@@ -873,8 +860,7 @@ func (t *Thinker) performPlatformObservation() {
} }
observationContent := fmt.Sprintf("[平台观察 %s]\n%s", time.Now().In(t.timeLocation).Format("15:04"), result.Summary) observationContent := fmt.Sprintf("[平台观察 %s]\n%s", time.Now().In(t.timeLocation).Format("15:04"), result.Summary)
if !t.muLock() { t.muLock()
return
defer t.muUnlock() defer t.muUnlock()
t.pendingThoughts = append(t.pendingThoughts, &PendingThought{ t.pendingThoughts = append(t.pendingThoughts, &PendingThought{
Content: observationContent, Content: observationContent,
@@ -907,8 +893,7 @@ func (t *Thinker) lightThinkLoop() {
log.Println("[后台思考] 轻量思考已停止") log.Println("[后台思考] 轻量思考已停止")
return return
case <-time.After(t.lightThinkInterval): case <-time.After(t.lightThinkInterval):
if !t.muLock() { t.muLock()
return
defer t.muUnlock() defer t.muUnlock()
sinceLastUser := time.Since(t.lastUserTime()) sinceLastUser := time.Since(t.lastUserTime())
sinceLastThink := time.Since(t.lastThinkTimeAtomic()) sinceLastThink := time.Since(t.lastThinkTimeAtomic())
@@ -970,8 +955,7 @@ func (t *Thinker) performLightThink() {
// Check if deep think should be woken. // Check if deep think should be woken.
if strings.Contains(content, "【需要深思】") { if strings.Contains(content, "【需要深思】") {
log.Println("[轻量思考] 检测到【需要深思】,唤醒深度思考...") log.Println("[轻量思考] 检测到【需要深思】,唤醒深度思考...")
if !t.muLock() { t.muLock()
return
defer t.muUnlock() defer t.muUnlock()
canDeep := time.Since(t.lastThinkTimeAtomic()) >= t.minThinkGap canDeep := time.Since(t.lastThinkTimeAtomic()) >= t.minThinkGap
@@ -987,8 +971,7 @@ func (t *Thinker) performLightThink() {
topic := strings.TrimSpace(content[idx+len("【话题发起】"):]) topic := strings.TrimSpace(content[idx+len("【话题发起】"):])
if topic != "" { if topic != "" {
log.Printf("[轻量思考] 话题发起: %s", topic) log.Printf("[轻量思考] 话题发起: %s", topic)
if !t.muLock() { t.muLock()
return
defer t.muUnlock() defer t.muUnlock()
pusher := t.messagePusher pusher := t.messagePusher
sessionID := t.activeSessionID sessionID := t.activeSessionID
@@ -1066,8 +1049,7 @@ func (t *Thinker) periodicThinkLoop() {
// GetPendingThoughts 获取并消费所有待处理的后台思考 // GetPendingThoughts 获取并消费所有待处理的后台思考
func (t *Thinker) GetPendingThoughts() []*PendingThought { func (t *Thinker) GetPendingThoughts() []*PendingThought {
if !t.muLock() { t.muLock()
return
defer t.muUnlock() defer t.muUnlock()
if len(t.pendingThoughts) == 0 { if len(t.pendingThoughts) == 0 {
@@ -1085,8 +1067,7 @@ func (t *Thinker) GetPendingThoughts() []*PendingThought {
// HasPendingThoughts 检查是否有待处理的思考 // HasPendingThoughts 检查是否有待处理的思考
func (t *Thinker) HasPendingThoughts() bool { func (t *Thinker) HasPendingThoughts() bool {
if !t.muLock() { t.muLock()
return
defer t.muUnlock() defer t.muUnlock()
return len(t.pendingThoughts) > 0 return len(t.pendingThoughts) > 0
} }
@@ -1098,8 +1079,7 @@ func (t *Thinker) HasPendingThoughts() bool {
// 防御性速率限制:即使调用方未检查 minThinkGapperformThink 自身也会 // 防御性速率限制:即使调用方未检查 minThinkGapperformThink 自身也会
// 强制执行最小间隔,防止并发调用或 bug 导致 LLM 配额被快速消耗。 // 强制执行最小间隔,防止并发调用或 bug 导致 LLM 配额被快速消耗。
func (t *Thinker) performThink(triggerReason string) { func (t *Thinker) performThink(triggerReason string) {
if !t.muLock() { t.muLock()
return
defer t.muUnlock() defer t.muUnlock()
gapSinceLast := time.Since(t.lastThinkTimeAtomic()) gapSinceLast := time.Since(t.lastThinkTimeAtomic())
minGap := t.minThinkGap minGap := t.minThinkGap
@@ -1120,16 +1100,14 @@ func (t *Thinker) performThink(triggerReason string) {
ctx, cancel := context.WithTimeout(context.Background(), 120*time.Second) ctx, cancel := context.WithTimeout(context.Background(), 120*time.Second)
defer cancel() defer cancel()
if !t.muLock() { t.muLock()
return
defer t.muUnlock() defer t.muUnlock()
t.thinkCancel = cancel t.thinkCancel = cancel
// 0. 让步于前台——如果用户最近有活动(非post_chat),跳过本次思考。 // 0. 让步于前台——如果用户最近有活动(非post_chat),跳过本次思考。
if triggerReason != "post_chat" { if triggerReason != "post_chat" {
if !t.muLock() { t.muLock()
return
defer t.muUnlock() defer t.muUnlock()
sinceLastUser := time.Since(t.lastUserTime()) sinceLastUser := time.Since(t.lastUserTime())
@@ -1143,8 +1121,7 @@ func (t *Thinker) performThink(triggerReason string) {
// 0. 让步于前台——如果用户最近有活动(非post_chat),跳过本次思考。 // 0. 让步于前台——如果用户最近有活动(非post_chat),跳过本次思考。
if triggerReason != "post_chat" { if triggerReason != "post_chat" {
if !t.muLock() { t.muLock()
return
defer t.muUnlock() defer t.muUnlock()
sinceLastUser := time.Since(t.lastUserTime()) sinceLastUser := time.Since(t.lastUserTime())
@@ -1164,8 +1141,7 @@ func (t *Thinker) performThink(triggerReason string) {
// 2. 获取当前活跃会话的对话历史(优先活跃会话,回退到管理员主会话) // 2. 获取当前活跃会话的对话历史(优先活跃会话,回退到管理员主会话)
var convHistory []model.LLMMessage var convHistory []model.LLMMessage
if t.convStore != nil { if t.convStore != nil {
if !t.muLock() { t.muLock()
return
defer t.muUnlock() defer t.muUnlock()
sessionID := t.activeSessionID sessionID := t.activeSessionID
if sessionID == "" { if sessionID == "" {
@@ -1283,8 +1259,7 @@ func (t *Thinker) performThink(triggerReason string) {
// 4.5 获取最近平台观察(定期触发和对话后触发时注入) // 4.5 获取最近平台观察(定期触发和对话后触发时注入)
var platformObservation string var platformObservation string
if triggerReason == "periodic" || triggerReason == "post_chat" { if triggerReason == "periodic" || triggerReason == "post_chat" {
if !t.muLock() { t.muLock()
return
defer t.muUnlock() defer t.muUnlock()
for i := len(t.pendingThoughts) - 1; i >= 0; i-- { for i := len(t.pendingThoughts) - 1; i >= 0; i-- {
if strings.HasPrefix(t.pendingThoughts[i].Content, "[平台观察") { if strings.HasPrefix(t.pendingThoughts[i].Content, "[平台观察") {
@@ -1435,8 +1410,7 @@ func (t *Thinker) performThink(triggerReason string) {
if len(parts) == 2 { if len(parts) == 2 {
adapterName, groupID := parts[0], parts[1] adapterName, groupID := parts[0], parts[1]
// Find the channel to get the correct platform type. // Find the channel to get the correct platform type.
if !t.muLock() { t.muLock()
return
defer t.muUnlock() defer t.muUnlock()
var platform string var platform string
for _, ch := range t.platformChannels { for _, ch := range t.platformChannels {
@@ -1690,8 +1664,7 @@ func (t *Thinker) buildThinkingUserPrompt(
case "post_chat": case "post_chat":
sb.WriteString("刚有人和你聊完天。你想自然地在心里回味一下刚才的对话……\n") sb.WriteString("刚有人和你聊完天。你想自然地在心里回味一下刚才的对话……\n")
case "silence": case "silence":
if !t.muLock() { t.muLock()
return
defer t.muUnlock() defer t.muUnlock()
silenceDuration := time.Since(t.lastUserTime()) silenceDuration := time.Since(t.lastUserTime())
@@ -1791,8 +1764,7 @@ func (t *Thinker) buildThinkingUserPrompt(
} }
// OBv11 platform identity and available channels for proactive messaging. // OBv11 platform identity and available channels for proactive messaging.
if !t.muLock() { t.muLock()
return
defer t.muUnlock() defer t.muUnlock()
qqChannels := t.platformChannels qqChannels := t.platformChannels
botUIDs := t.botUIDs botUIDs := t.botUIDs
@@ -1941,8 +1913,7 @@ func (t *Thinker) buildOpenAITools() []llm.OpenAITool {
// storeThought 存储思考结果到待推送队列,并异步持久化到 memory-service // storeThought 存储思考结果到待推送队列,并异步持久化到 memory-service
func (t *Thinker) storeThought(content string, toolCallsJSON string, toolCallCount int) { func (t *Thinker) storeThought(content string, toolCallsJSON string, toolCallCount int) {
if !t.muLock() { t.muLock()
return
defer t.muUnlock() defer t.muUnlock()
t.pendingThoughts = append(t.pendingThoughts, &PendingThought{ t.pendingThoughts = append(t.pendingThoughts, &PendingThought{
Content: content, Content: content,
@@ -2118,8 +2089,7 @@ func (t *Thinker) extractProactiveMessage(content string) (string, *ProactiveTar
channelID = "private_" + m[2] channelID = "private_" + m[2]
} }
adapterName := platform // fallback to format key adapterName := platform // fallback to format key
if !t.muLock() { t.muLock()
return
defer t.muUnlock() defer t.muUnlock()
for _, ch := range t.platformChannels { for _, ch := range t.platformChannels {
if ch.Platform == platform && ch.ChannelType == chatType && ch.ChannelID == channelID { if ch.Platform == platform && ch.ChannelType == chatType && ch.ChannelID == channelID {
@@ -2711,8 +2681,7 @@ func (t *Thinker) setLastProactive(ts time.Time) { t.lastProactiveNs.Store(ts.Un
func (t *Thinker) DeadlockDetected(timeout time.Duration) bool { func (t *Thinker) DeadlockDetected(timeout time.Duration) bool {
done := make(chan struct{}) done := make(chan struct{})
go func() { go func() {
if !t.muLock() { t.muLock()
return
defer t.muUnlock() defer t.muUnlock()
close(done) close(done)
@@ -2738,8 +2707,7 @@ func (t *Thinker) StartDeadlockMonitor() {
for range ticker.C { for range ticker.C {
done := make(chan struct{}) done := make(chan struct{})
go func() { go func() {
if !t.muLock() { t.muLock()
return
defer t.muUnlock() defer t.muUnlock()
close(done) close(done)