fix: 第四轮调试 — 回复去重/消息时序/UI布局/自主思考深度优化 + 文档重整

后端修复:
- main.go: 恢复 /api/v1/chat 路由中丢失的 handleChat 调用 (空响应回归)
- orchestrator.go: splitChatByLines 改为双换行分割, 避免单换行误拆
- chat_handler.go: multi_message 增加 !hasReview 守卫, 消息延迟 200→800ms
- thinker.go: RecordUserMessage 追踪活跃会话ID, 推送主动消息到正确会话
- thinker.go: 增强思考提示词 — 禁止在用户休息/离开时发送主动消息

前端修复:
- useWebSocket.ts: stream_segments 不再创建消息气泡, 消除重复回复
- MessageBubble.tsx: 动作消息居左对齐无头像, 时间戳移至气泡外侧 hover 显示
- ChatInput.tsx: 昔涟输入提示移至输入框上方, 波点动画效果
- MessageList/TypingIndicator/ChatContainer: 清理冗余 isTyping 传递
- MemoryPanel.tsx: 新增记忆面板组件

文档重整:
- docs/debug/ → docs/debug_log/ 重命名统一
- 新增 debug_log/README.md 索引
- .gitignore: 新增 android/ 排除规则

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
This commit is contained in:
2026-05-23 13:09:18 +08:00
parent 0c1bbff7b4
commit b123a36aae
37 changed files with 580 additions and 174 deletions
@@ -229,6 +229,14 @@ func (h *ChatHandler) streamResponse(client *ws.Client, mode string, reqBody []b
// 增大 scanner buffer 以处理大块 SSE 数据
scanner.Buffer(make([]byte, 0, 64*1024), 1024*1024)
// 通知前端 AI 开始生成回复
client.SendMessage(ws.ServerMessage{
Type: "stream_start",
MessageID: "msg_" + generateID(),
SessionID: client.SessionID,
Timestamp: time.Now().UnixMilli(),
})
var fullText string
var msgID string
var hasReview bool // 是否有审查消息(避免重复持久化)
@@ -325,7 +333,7 @@ func (h *ChatHandler) streamResponse(client *ws.Client, mode string, reqBody []b
})
// 小延迟让消息逐条到达,更像真人
if i < len(chunk.ReviewMessages)-1 {
time.Sleep(200 * time.Millisecond)
time.Sleep(800 * time.Millisecond)
}
}
hasReview = true
@@ -351,18 +359,9 @@ func (h *ChatHandler) streamResponse(client *ws.Client, mode string, reqBody []b
continue
}
// 逐 delta 转发
// 逐 delta 积累(不再逐块转发,由审查消息代替)
if chunk.Delta != "" {
fullText += chunk.Delta
client.SendMessage(ws.ServerMessage{
Type: "stream_chunk",
MessageID: msgID,
Content: chunk.Delta,
Role: "assistant",
SessionID: client.SessionID,
Timestamp: time.Now().UnixMilli(),
})
}
}
@@ -383,8 +382,9 @@ func (h *ChatHandler) streamResponse(client *ws.Client, mode string, reqBody []b
}
// 检测是否为多消息格式(包含空行分隔的多条消息)
// 如果已有审查消息则跳过,避免与 review_messages 重复
multiParts := parseMultiMessage(fullText)
if len(multiParts) > 1 {
if !hasReview && len(multiParts) > 1 {
// 发送 multi_message 事件
var items []ws.MultiMessageItem
for i, part := range multiParts {