feat: Phase 1+2 架构进化 — 连续思考链/主动消息决策/情感状态机/离线自主思考 (86文件)
Phase 1 (基础设施): - ThinkChain 思考链连续性 + 差异化思考提示词 (persistent) - AutonomousToolPolicy 工具安全策略 (safe/unsafe/conditional) - MessageScheduler 自适应消息节奏 (Idle/Available/Busy) - SessionEnrichmentStore 渐进式上下文丰富 (5层) - ConversationBus 事件总线 + ResponseCache (dedup) - pkg/logger 统一日志 + 所有 handler 替换 fmt.Printf - NPE 守卫/链路优化/数据库表修复/Go workspace Phase 2 (人格交互): - EmotionState/EmotionTracker 情感状态机 (5种心情, 情绪衰减) - ProactiveGuard 主动消息多维决策 (静默时段/紧急度/频率/校验) - Gateway↔ai-core 在线状态感知链路 (presence notification) - 离线思考频率控制 + 重连问候 + 离线消息排队 Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
This commit is contained in:
@@ -3,7 +3,7 @@ package handler
|
||||
import (
|
||||
"database/sql"
|
||||
"fmt"
|
||||
"log"
|
||||
"github.com/yourname/cyrene-ai/pkg/logger"
|
||||
"net/http"
|
||||
"regexp"
|
||||
"strings"
|
||||
@@ -167,12 +167,12 @@ func (h *AuthHandler) Login(c *gin.Context) {
|
||||
// 密码正确,迁移 admin 到 users 表
|
||||
passwordHash, err := bcrypt.GenerateFromPassword([]byte(req.Password), bcrypt.DefaultCost)
|
||||
if err != nil {
|
||||
log.Printf("⚠ 迁移管理员密码哈希失败: %v", err)
|
||||
logger.Printf("⚠ 迁移管理员密码哈希失败: %v", err)
|
||||
} else {
|
||||
if _, err := store.CreateUser(h.db, req.Username, string(passwordHash), true); err != nil {
|
||||
log.Printf("⚠ 迁移管理员到 users 表失败: %v", err)
|
||||
logger.Printf("⚠ 迁移管理员到 users 表失败: %v", err)
|
||||
} else {
|
||||
log.Println("✅ 管理员已迁移到 users 表")
|
||||
logger.Println("✅ 管理员已迁移到 users 表")
|
||||
}
|
||||
}
|
||||
userID = "admin"
|
||||
|
||||
@@ -4,7 +4,7 @@ import (
|
||||
"crypto/rand"
|
||||
"encoding/hex"
|
||||
"encoding/json"
|
||||
"log"
|
||||
"github.com/yourname/cyrene-ai/pkg/logger"
|
||||
"net/http"
|
||||
|
||||
"github.com/gin-gonic/gin"
|
||||
@@ -76,7 +76,7 @@ func (h *AutomationHandler) ListRules(c *gin.Context) {
|
||||
|
||||
rules, err := h.store.GetRulesByUser(userID)
|
||||
if err != nil {
|
||||
log.Printf("[automation] 获取规则列表失败: %v", err)
|
||||
logger.Printf("[automation] 获取规则列表失败: %v", err)
|
||||
c.JSON(http.StatusInternalServerError, gin.H{"error": "获取规则列表失败"})
|
||||
return
|
||||
}
|
||||
@@ -124,7 +124,7 @@ func (h *AutomationHandler) CreateRule(c *gin.Context) {
|
||||
}
|
||||
|
||||
if err := h.store.CreateRule(rule); err != nil {
|
||||
log.Printf("[automation] 创建规则失败: %v", err)
|
||||
logger.Printf("[automation] 创建规则失败: %v", err)
|
||||
c.JSON(http.StatusInternalServerError, gin.H{"error": "创建规则失败"})
|
||||
return
|
||||
}
|
||||
@@ -140,7 +140,7 @@ func (h *AutomationHandler) GetRule(c *gin.Context) {
|
||||
id := c.Param("id")
|
||||
rule, err := h.store.GetRule(id)
|
||||
if err != nil {
|
||||
log.Printf("[automation] 获取规则失败: %v", err)
|
||||
logger.Printf("[automation] 获取规则失败: %v", err)
|
||||
c.JSON(http.StatusInternalServerError, gin.H{"error": "获取规则失败"})
|
||||
return
|
||||
}
|
||||
@@ -161,7 +161,7 @@ func (h *AutomationHandler) UpdateRule(c *gin.Context) {
|
||||
// 先获取规则验证所有权
|
||||
existing, err := h.store.GetRule(id)
|
||||
if err != nil {
|
||||
log.Printf("[automation] 获取规则失败: %v", err)
|
||||
logger.Printf("[automation] 获取规则失败: %v", err)
|
||||
c.JSON(http.StatusInternalServerError, gin.H{"error": "获取规则失败"})
|
||||
return
|
||||
}
|
||||
@@ -204,7 +204,7 @@ func (h *AutomationHandler) UpdateRule(c *gin.Context) {
|
||||
}
|
||||
|
||||
if err := h.store.UpdateRule(existing); err != nil {
|
||||
log.Printf("[automation] 更新规则失败: %v", err)
|
||||
logger.Printf("[automation] 更新规则失败: %v", err)
|
||||
c.JSON(http.StatusInternalServerError, gin.H{"error": "更新规则失败"})
|
||||
return
|
||||
}
|
||||
@@ -223,7 +223,7 @@ func (h *AutomationHandler) DeleteRule(c *gin.Context) {
|
||||
|
||||
existing, err := h.store.GetRule(id)
|
||||
if err != nil {
|
||||
log.Printf("[automation] 获取规则失败: %v", err)
|
||||
logger.Printf("[automation] 获取规则失败: %v", err)
|
||||
c.JSON(http.StatusInternalServerError, gin.H{"error": "获取规则失败"})
|
||||
return
|
||||
}
|
||||
@@ -237,7 +237,7 @@ func (h *AutomationHandler) DeleteRule(c *gin.Context) {
|
||||
}
|
||||
|
||||
if err := h.store.DeleteRule(id); err != nil {
|
||||
log.Printf("[automation] 删除规则失败: %v", err)
|
||||
logger.Printf("[automation] 删除规则失败: %v", err)
|
||||
c.JSON(http.StatusInternalServerError, gin.H{"error": "删除规则失败"})
|
||||
return
|
||||
}
|
||||
@@ -253,7 +253,7 @@ func (h *AutomationHandler) TriggerRule(c *gin.Context) {
|
||||
|
||||
rule, err := h.store.GetRule(id)
|
||||
if err != nil {
|
||||
log.Printf("[automation] 获取规则失败: %v", err)
|
||||
logger.Printf("[automation] 获取规则失败: %v", err)
|
||||
c.JSON(http.StatusInternalServerError, gin.H{"error": "获取规则失败"})
|
||||
return
|
||||
}
|
||||
@@ -288,7 +288,7 @@ func (h *AutomationHandler) ListScenes(c *gin.Context) {
|
||||
|
||||
scenes, err := h.store.GetScenesByUser(userID)
|
||||
if err != nil {
|
||||
log.Printf("[automation] 获取场景列表失败: %v", err)
|
||||
logger.Printf("[automation] 获取场景列表失败: %v", err)
|
||||
c.JSON(http.StatusInternalServerError, gin.H{"error": "获取场景列表失败"})
|
||||
return
|
||||
}
|
||||
@@ -325,7 +325,7 @@ func (h *AutomationHandler) CreateScene(c *gin.Context) {
|
||||
}
|
||||
|
||||
if err := h.store.CreateScene(scene); err != nil {
|
||||
log.Printf("[automation] 创建场景失败: %v", err)
|
||||
logger.Printf("[automation] 创建场景失败: %v", err)
|
||||
c.JSON(http.StatusInternalServerError, gin.H{"error": "创建场景失败"})
|
||||
return
|
||||
}
|
||||
@@ -341,7 +341,7 @@ func (h *AutomationHandler) GetScene(c *gin.Context) {
|
||||
id := c.Param("id")
|
||||
scene, err := h.store.GetScene(id)
|
||||
if err != nil {
|
||||
log.Printf("[automation] 获取场景失败: %v", err)
|
||||
logger.Printf("[automation] 获取场景失败: %v", err)
|
||||
c.JSON(http.StatusInternalServerError, gin.H{"error": "获取场景失败"})
|
||||
return
|
||||
}
|
||||
@@ -361,7 +361,7 @@ func (h *AutomationHandler) UpdateScene(c *gin.Context) {
|
||||
|
||||
existing, err := h.store.GetScene(id)
|
||||
if err != nil {
|
||||
log.Printf("[automation] 获取场景失败: %v", err)
|
||||
logger.Printf("[automation] 获取场景失败: %v", err)
|
||||
c.JSON(http.StatusInternalServerError, gin.H{"error": "获取场景失败"})
|
||||
return
|
||||
}
|
||||
@@ -391,7 +391,7 @@ func (h *AutomationHandler) UpdateScene(c *gin.Context) {
|
||||
}
|
||||
|
||||
if err := h.store.UpdateScene(existing); err != nil {
|
||||
log.Printf("[automation] 更新场景失败: %v", err)
|
||||
logger.Printf("[automation] 更新场景失败: %v", err)
|
||||
c.JSON(http.StatusInternalServerError, gin.H{"error": "更新场景失败"})
|
||||
return
|
||||
}
|
||||
@@ -410,7 +410,7 @@ func (h *AutomationHandler) DeleteScene(c *gin.Context) {
|
||||
|
||||
existing, err := h.store.GetScene(id)
|
||||
if err != nil {
|
||||
log.Printf("[automation] 获取场景失败: %v", err)
|
||||
logger.Printf("[automation] 获取场景失败: %v", err)
|
||||
c.JSON(http.StatusInternalServerError, gin.H{"error": "获取场景失败"})
|
||||
return
|
||||
}
|
||||
@@ -424,7 +424,7 @@ func (h *AutomationHandler) DeleteScene(c *gin.Context) {
|
||||
}
|
||||
|
||||
if err := h.store.DeleteScene(id); err != nil {
|
||||
log.Printf("[automation] 删除场景失败: %v", err)
|
||||
logger.Printf("[automation] 删除场景失败: %v", err)
|
||||
c.JSON(http.StatusInternalServerError, gin.H{"error": "删除场景失败"})
|
||||
return
|
||||
}
|
||||
@@ -440,7 +440,7 @@ func (h *AutomationHandler) ExecuteScene(c *gin.Context) {
|
||||
// 验证场景存在
|
||||
scene, err := h.store.GetScene(id)
|
||||
if err != nil {
|
||||
log.Printf("[automation] 获取场景失败: %v", err)
|
||||
logger.Printf("[automation] 获取场景失败: %v", err)
|
||||
c.JSON(http.StatusInternalServerError, gin.H{"error": "获取场景失败"})
|
||||
return
|
||||
}
|
||||
@@ -452,7 +452,7 @@ func (h *AutomationHandler) ExecuteScene(c *gin.Context) {
|
||||
userID := middleware.GetUserID(c)
|
||||
|
||||
if err := h.engine.ExecuteScene(id, userID); err != nil {
|
||||
log.Printf("[automation] 执行场景失败: %v", err)
|
||||
logger.Printf("[automation] 执行场景失败: %v", err)
|
||||
c.JSON(http.StatusInternalServerError, gin.H{"error": "执行场景失败"})
|
||||
return
|
||||
}
|
||||
|
||||
@@ -5,7 +5,7 @@ import (
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"io"
|
||||
"log"
|
||||
"github.com/yourname/cyrene-ai/pkg/logger"
|
||||
"net/http"
|
||||
"strings"
|
||||
"time"
|
||||
@@ -66,7 +66,7 @@ func (h *BriefingHandler) GetBriefing(c *gin.Context) {
|
||||
|
||||
briefing, err := h.briefingStore.GetBriefingByDate(userID, date)
|
||||
if err != nil {
|
||||
log.Printf("[briefing] 查询简报失败: user=%s date=%s err=%v", userID, date, err)
|
||||
logger.Printf("[briefing] 查询简报失败: user=%s date=%s err=%v", userID, date, err)
|
||||
c.JSON(http.StatusInternalServerError, gin.H{"error": "查询简报失败: " + err.Error()})
|
||||
return
|
||||
}
|
||||
@@ -106,7 +106,7 @@ func (h *BriefingHandler) GetLatestBriefings(c *gin.Context) {
|
||||
|
||||
briefings, err := h.briefingStore.GetLatestBriefings(userID, limit)
|
||||
if err != nil {
|
||||
log.Printf("[briefing] 查询简报列表失败: user=%s err=%v", userID, err)
|
||||
logger.Printf("[briefing] 查询简报列表失败: user=%s err=%v", userID, err)
|
||||
c.JSON(http.StatusInternalServerError, gin.H{"error": "查询简报列表失败: " + err.Error()})
|
||||
return
|
||||
}
|
||||
@@ -139,7 +139,7 @@ func (h *BriefingHandler) Generate(c *gin.Context) {
|
||||
|
||||
result, err := h.GenerateDailyBriefing(req.UserID)
|
||||
if err != nil {
|
||||
log.Printf("[briefing] 生成简报失败: user=%s err=%v", req.UserID, err)
|
||||
logger.Printf("[briefing] 生成简报失败: user=%s err=%v", req.UserID, err)
|
||||
c.JSON(http.StatusInternalServerError, gin.H{
|
||||
"error": "生成简报失败: " + err.Error(),
|
||||
"success": false,
|
||||
@@ -173,10 +173,10 @@ func (h *BriefingHandler) GenerateDailyBriefing(userID string) (*store.Briefing,
|
||||
}
|
||||
|
||||
// 1. 获取天气数据
|
||||
log.Printf("[briefing] 获取天气数据...")
|
||||
logger.Printf("[briefing] 获取天气数据...")
|
||||
weather, err := h.fetchWeather("Shanghai")
|
||||
if err != nil {
|
||||
log.Printf("[briefing] 天气获取失败 (降级): %v", err)
|
||||
logger.Printf("[briefing] 天气获取失败 (降级): %v", err)
|
||||
weather = &store.WeatherData{
|
||||
Location: "未知",
|
||||
Temp: 0,
|
||||
@@ -185,13 +185,13 @@ func (h *BriefingHandler) GenerateDailyBriefing(userID string) (*store.Briefing,
|
||||
}
|
||||
}
|
||||
briefing.Weather = weather
|
||||
log.Printf("[briefing] 天气: %s %.1f°C %s", weather.Location, weather.Temp, weather.Condition)
|
||||
logger.Printf("[briefing] 天气: %s %.1f°C %s", weather.Location, weather.Temp, weather.Condition)
|
||||
|
||||
// 2. 获取今日待办提醒
|
||||
log.Printf("[briefing] 获取待办提醒...")
|
||||
logger.Printf("[briefing] 获取待办提醒...")
|
||||
reminders, err := h.reminderStore.GetRemindersByUser(userID, "pending", 10, 0)
|
||||
if err != nil {
|
||||
log.Printf("[briefing] 获取提醒失败: %v", err)
|
||||
logger.Printf("[briefing] 获取提醒失败: %v", err)
|
||||
} else {
|
||||
now := time.Now()
|
||||
endOfDay := time.Date(now.Year(), now.Month(), now.Day(), 23, 59, 59, 0, now.Location())
|
||||
@@ -205,22 +205,22 @@ func (h *BriefingHandler) GenerateDailyBriefing(userID string) (*store.Briefing,
|
||||
}
|
||||
}
|
||||
}
|
||||
log.Printf("[briefing] 今日待办: %d 项", len(briefing.Reminders))
|
||||
logger.Printf("[briefing] 今日待办: %d 项", len(briefing.Reminders))
|
||||
|
||||
// 3. 获取新闻摘要(通过 tool-engine web_search)
|
||||
log.Printf("[briefing] 获取新闻摘要...")
|
||||
logger.Printf("[briefing] 获取新闻摘要...")
|
||||
news, err := h.fetchNews()
|
||||
if err != nil {
|
||||
log.Printf("[briefing] 新闻获取失败 (降级): %v", err)
|
||||
logger.Printf("[briefing] 新闻获取失败 (降级): %v", err)
|
||||
}
|
||||
briefing.News = news
|
||||
log.Printf("[briefing] 新闻: %d 条", len(news))
|
||||
logger.Printf("[briefing] 新闻: %d 条", len(news))
|
||||
|
||||
// 4. 生成 AI 摘要
|
||||
log.Printf("[briefing] 生成 AI 摘要...")
|
||||
logger.Printf("[briefing] 生成 AI 摘要...")
|
||||
summary, err := h.generateAISummary(briefing)
|
||||
if err != nil {
|
||||
log.Printf("[briefing] AI 摘要生成失败 (降级): %v", err)
|
||||
logger.Printf("[briefing] AI 摘要生成失败 (降级): %v", err)
|
||||
summary = h.buildFallbackSummary(briefing)
|
||||
briefing.SummarySource = "fallback"
|
||||
} else {
|
||||
@@ -238,7 +238,7 @@ func (h *BriefingHandler) GenerateDailyBriefing(userID string) (*store.Briefing,
|
||||
return nil, fmt.Errorf("保存简报失败: %w", err)
|
||||
}
|
||||
|
||||
log.Printf("[briefing] 简报已生成: user=%s date=%s", userID, today)
|
||||
logger.Printf("[briefing] 简报已生成: user=%s date=%s", userID, today)
|
||||
return briefing, nil
|
||||
}
|
||||
|
||||
@@ -362,7 +362,7 @@ func (h *BriefingHandler) fetchNews() ([]store.NewsItem, error) {
|
||||
}
|
||||
|
||||
if result.Error != "" {
|
||||
log.Printf("[briefing] 新闻搜索失败: %s", result.Error)
|
||||
logger.Printf("[briefing] 新闻搜索失败: %s", result.Error)
|
||||
// 返回降级新闻
|
||||
return []store.NewsItem{
|
||||
{
|
||||
@@ -585,7 +585,7 @@ func (h *BriefingHandler) pushBriefingNotification(userID string, b *store.Brief
|
||||
|
||||
data, err := json.Marshal(msg)
|
||||
if err != nil {
|
||||
log.Printf("[briefing] 序列化简报通知失败: %v", err)
|
||||
logger.Printf("[briefing] 序列化简报通知失败: %v", err)
|
||||
return
|
||||
}
|
||||
|
||||
@@ -596,10 +596,10 @@ func (h *BriefingHandler) pushBriefingNotification(userID string, b *store.Brief
|
||||
b.Status = "delivered"
|
||||
b.DeliveredAt = &now
|
||||
if err := h.briefingStore.CreateOrUpdateBriefing(b); err != nil {
|
||||
log.Printf("[briefing] 更新简报送达状态失败: %v", err)
|
||||
logger.Printf("[briefing] 更新简报送达状态失败: %v", err)
|
||||
}
|
||||
|
||||
log.Printf("[briefing] 简报通知已推送: user=%s date=%s", userID, b.Date)
|
||||
logger.Printf("[briefing] 简报通知已推送: user=%s date=%s", userID, b.Date)
|
||||
}
|
||||
|
||||
// StartBriefingScheduler 启动简报调度器
|
||||
@@ -614,7 +614,7 @@ func StartBriefingScheduler(handler *BriefingHandler, briefingStore *store.Brief
|
||||
ticker := time.NewTicker(30 * time.Second)
|
||||
defer ticker.Stop()
|
||||
|
||||
log.Printf("[BriefingScheduler] 简报调度器已启动 (简报时间: %s)", briefingTime)
|
||||
logger.Printf("[BriefingScheduler] 简报调度器已启动 (简报时间: %s)", briefingTime)
|
||||
|
||||
// 记录今天是否已触发
|
||||
lastTriggeredDate := ""
|
||||
@@ -626,13 +626,13 @@ func StartBriefingScheduler(handler *BriefingHandler, briefingStore *store.Brief
|
||||
|
||||
// 检查是否到达简报时间且今天尚未触发
|
||||
if currentTime == briefingTime && currentDate != lastTriggeredDate {
|
||||
log.Printf("[BriefingScheduler] 触发每日简报生成: %s", currentDate)
|
||||
logger.Printf("[BriefingScheduler] 触发每日简报生成: %s", currentDate)
|
||||
lastTriggeredDate = currentDate
|
||||
|
||||
// 获取所有用户
|
||||
users, err := briefingStore.GetAllUsers()
|
||||
if err != nil {
|
||||
log.Printf("[BriefingScheduler] 获取用户列表失败: %v", err)
|
||||
logger.Printf("[BriefingScheduler] 获取用户列表失败: %v", err)
|
||||
continue
|
||||
}
|
||||
|
||||
@@ -642,21 +642,21 @@ func StartBriefingScheduler(handler *BriefingHandler, briefingStore *store.Brief
|
||||
}
|
||||
|
||||
if len(users) == 0 {
|
||||
log.Println("[BriefingScheduler] 没有找到用户,跳过简报生成")
|
||||
logger.Println("[BriefingScheduler] 没有找到用户,跳过简报生成")
|
||||
continue
|
||||
}
|
||||
|
||||
for _, userID := range users {
|
||||
log.Printf("[BriefingScheduler] 为用户 %s 生成简报...", userID)
|
||||
logger.Printf("[BriefingScheduler] 为用户 %s 生成简报...", userID)
|
||||
result, err := handler.GenerateDailyBriefing(userID)
|
||||
if err != nil {
|
||||
log.Printf("[BriefingScheduler] 生成简报失败: user=%s err=%v", userID, err)
|
||||
logger.Printf("[BriefingScheduler] 生成简报失败: user=%s err=%v", userID, err)
|
||||
continue
|
||||
}
|
||||
handler.pushBriefingNotification(userID, result)
|
||||
}
|
||||
|
||||
log.Printf("[BriefingScheduler] 每日简报已生成完毕,共 %d 个用户", len(users))
|
||||
logger.Printf("[BriefingScheduler] 每日简报已生成完毕,共 %d 个用户", len(users))
|
||||
}
|
||||
}
|
||||
}()
|
||||
|
||||
@@ -8,7 +8,7 @@ import (
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"io"
|
||||
"log"
|
||||
"github.com/yourname/cyrene-ai/pkg/logger"
|
||||
"net/http"
|
||||
"strings"
|
||||
"time"
|
||||
@@ -88,7 +88,7 @@ func (h *ChatHandler) HandleWebSocket(c *gin.Context) {
|
||||
// 升级WebSocket连接
|
||||
conn, err := h.upgrader.Upgrade(c.Writer, c.Request, nil)
|
||||
if err != nil {
|
||||
log.Printf("[WS] 升级连接失败: %v", err)
|
||||
logger.Printf("[WS] 升级连接失败: %v", err)
|
||||
return
|
||||
}
|
||||
|
||||
@@ -115,7 +115,7 @@ func (h *ChatHandler) handleMessage(client *ws.Client, msg ws.ClientMessage) {
|
||||
case "history":
|
||||
h.handleHistoryRequest(client, msg)
|
||||
default:
|
||||
log.Printf("[WS] 未知消息类型: %s from user=%s", msg.Type, client.UserID)
|
||||
logger.Printf("[WS] 未知消息类型: %s from user=%s", msg.Type, client.UserID)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -128,8 +128,8 @@ func (h *ChatHandler) handleChatMessage(client *ws.Client, msg ws.ClientMessage)
|
||||
|
||||
// 持久化用户消息到数据库(在 WebSocket 发送之前)
|
||||
if h.sessionStore != nil && h.sessionStore.IsAvailable() {
|
||||
if err := h.sessionStore.AddMessage(client.SessionID, "user", msg.Content); err != nil {
|
||||
log.Printf("[chat] 持久化用户消息失败: %v", err)
|
||||
if err := h.sessionStore.AddMessage(client.SessionID, "user", "chat", msg.Content); err != nil {
|
||||
logger.Printf("[chat] 持久化用户消息失败: %v", err)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -151,7 +151,7 @@ func (h *ChatHandler) handleChatMessage(client *ws.Client, msg ws.ClientMessage)
|
||||
}
|
||||
reqBody, err := json.Marshal(aiReq)
|
||||
if err != nil {
|
||||
log.Printf("[chat] 序列化请求失败: %v", err)
|
||||
logger.Printf("[chat] 序列化请求失败: %v", err)
|
||||
h.hub.UpdateSessionState(client.SessionID, "error")
|
||||
client.SendMessage(ws.ServerMessage{
|
||||
Type: "error",
|
||||
@@ -183,7 +183,7 @@ func (h *ChatHandler) streamResponse(client *ws.Client, mode string, reqBody []b
|
||||
aiCoreURL := h.cfg.AICoreURL + "/api/v1/chat"
|
||||
httpReq, err := http.NewRequest("POST", aiCoreURL, bytes.NewReader(reqBody))
|
||||
if err != nil {
|
||||
log.Printf("[chat] 创建 AI-Core 请求失败: %v", err)
|
||||
logger.Printf("[chat] 创建 AI-Core 请求失败: %v", err)
|
||||
h.hub.UpdateSessionState(client.SessionID, "error")
|
||||
client.SendMessage(ws.ServerMessage{
|
||||
Type: "error",
|
||||
@@ -199,7 +199,7 @@ func (h *ChatHandler) streamResponse(client *ws.Client, mode string, reqBody []b
|
||||
httpClient := &http.Client{Timeout: 120 * time.Second}
|
||||
resp, err := httpClient.Do(httpReq)
|
||||
if err != nil {
|
||||
log.Printf("[chat] AI-Core 调用失败: %v", err)
|
||||
logger.Printf("[chat] AI-Core 调用失败: %v", err)
|
||||
h.hub.UpdateSessionState(client.SessionID, "error")
|
||||
client.SendMessage(ws.ServerMessage{
|
||||
Type: "error",
|
||||
@@ -213,7 +213,7 @@ func (h *ChatHandler) streamResponse(client *ws.Client, mode string, reqBody []b
|
||||
|
||||
if resp.StatusCode != http.StatusOK {
|
||||
body, _ := io.ReadAll(resp.Body)
|
||||
log.Printf("[chat] AI-Core 返回错误 [%d]: %s", resp.StatusCode, string(body))
|
||||
logger.Printf("[chat] AI-Core 返回错误 [%d]: %s", resp.StatusCode, string(body))
|
||||
h.hub.UpdateSessionState(client.SessionID, "error")
|
||||
client.SendMessage(ws.ServerMessage{
|
||||
Type: "error",
|
||||
@@ -273,13 +273,13 @@ func (h *ChatHandler) streamResponse(client *ws.Client, mode string, reqBody []b
|
||||
ReviewMessages []ws.ReviewMessage `json:"review_messages,omitempty"`
|
||||
}
|
||||
if err := json.Unmarshal([]byte(data), &chunk); err != nil {
|
||||
log.Printf("[chat] 解析 SSE delta 失败: %v, raw=%s", err, data)
|
||||
logger.Printf("[chat] 解析 SSE delta 失败: %v, raw=%s", err, data)
|
||||
continue
|
||||
}
|
||||
|
||||
// 错误处理
|
||||
if chunk.Error != "" {
|
||||
log.Printf("[chat] AI-Core 流式错误: %s", chunk.Error)
|
||||
logger.Printf("[chat] AI-Core 流式错误: %s", chunk.Error)
|
||||
h.hub.UpdateSessionState(client.SessionID, "error")
|
||||
client.SendMessage(ws.ServerMessage{
|
||||
Type: "error",
|
||||
@@ -312,8 +312,8 @@ func (h *ChatHandler) streamResponse(client *ws.Client, mode string, reqBody []b
|
||||
reviewMsgID := fmt.Sprintf("%s_r%d", msgID, i)
|
||||
// 持久化每条审查消息
|
||||
if h.sessionStore != nil && h.sessionStore.IsAvailable() {
|
||||
if err := h.sessionStore.AddMessage(client.SessionID, role, rm.Content); err != nil {
|
||||
log.Printf("[chat] 持久化审查消息失败: %v", err)
|
||||
if err := h.sessionStore.AddMessage(client.SessionID, role, msgType, rm.Content); err != nil {
|
||||
logger.Printf("[chat] 持久化审查消息失败: %v", err)
|
||||
}
|
||||
}
|
||||
h.hub.CacheMessage(client.UserID, client.SessionID, ws.Message{
|
||||
@@ -331,9 +331,9 @@ func (h *ChatHandler) streamResponse(client *ws.Client, mode string, reqBody []b
|
||||
SessionID: client.SessionID,
|
||||
Timestamp: time.Now().UnixMilli(),
|
||||
})
|
||||
// 小延迟让消息逐条到达,更像真人
|
||||
if i < len(chunk.ReviewMessages)-1 {
|
||||
time.Sleep(800 * time.Millisecond)
|
||||
// 使用 MessageScheduler 计算的 per-message 延迟
|
||||
if rm.DelayMs > 0 {
|
||||
time.Sleep(time.Duration(rm.DelayMs) * time.Millisecond)
|
||||
}
|
||||
}
|
||||
hasReview = true
|
||||
@@ -366,7 +366,7 @@ func (h *ChatHandler) streamResponse(client *ws.Client, mode string, reqBody []b
|
||||
}
|
||||
|
||||
if err := scanner.Err(); err != nil {
|
||||
log.Printf("[chat] SSE 读取错误: %v", err)
|
||||
logger.Printf("[chat] SSE 读取错误: %v", err)
|
||||
h.hub.UpdateSessionState(client.SessionID, "error")
|
||||
client.SendMessage(ws.ServerMessage{
|
||||
Type: "error",
|
||||
@@ -416,8 +416,8 @@ func (h *ChatHandler) streamResponse(client *ws.Client, mode string, reqBody []b
|
||||
// 如果有审查消息,每条已单独持久化,跳过 fullText 以避免重复
|
||||
if !hasReview && fullText != "" {
|
||||
if h.sessionStore != nil && h.sessionStore.IsAvailable() {
|
||||
if err := h.sessionStore.AddMessage(client.SessionID, "assistant", fullText); err != nil {
|
||||
log.Printf("[chat] 持久化 AI 回复失败: %v", err)
|
||||
if err := h.sessionStore.AddMessage(client.SessionID, "assistant", "chat", fullText); err != nil {
|
||||
logger.Printf("[chat] 持久化 AI 回复失败: %v", err)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -466,18 +466,20 @@ func (h *ChatHandler) handleHistoryRequest(client *ws.Client, msg ws.ClientMessa
|
||||
if len(messages) == 0 && h.sessionStore != nil && h.sessionStore.IsAvailable() {
|
||||
dbMessages, err := h.sessionStore.GetMessages(sessionID, 50, 0)
|
||||
if err == nil && len(dbMessages) > 0 {
|
||||
log.Printf("[history] 从数据库恢复会话历史: session=%s, %d 条消息", sessionID, len(dbMessages))
|
||||
logger.Printf("[history] 从数据库恢复会话历史: session=%s, %d 条消息", sessionID, len(dbMessages))
|
||||
// 恢复到内存缓存
|
||||
for _, dbMsg := range dbMessages {
|
||||
messages = append(messages, ws.Message{
|
||||
ID: fmt.Sprintf("db_%d", dbMsg.ID),
|
||||
Role: dbMsg.Role,
|
||||
MsgType: dbMsg.MsgType,
|
||||
Content: dbMsg.Content,
|
||||
Timestamp: dbMsg.CreatedAt.UnixMilli(),
|
||||
})
|
||||
h.hub.CacheMessage(client.UserID, sessionID, ws.Message{
|
||||
ID: fmt.Sprintf("db_%d", dbMsg.ID),
|
||||
Role: dbMsg.Role,
|
||||
MsgType: dbMsg.MsgType,
|
||||
Content: dbMsg.Content,
|
||||
Timestamp: dbMsg.CreatedAt.UnixMilli(),
|
||||
})
|
||||
@@ -497,7 +499,7 @@ func (h *ChatHandler) handleHistoryRequest(client *ws.Client, msg ws.ClientMessa
|
||||
}
|
||||
|
||||
if err := client.SendMessage(response); err != nil {
|
||||
log.Printf("[WS] 发送历史消息失败: %v", err)
|
||||
logger.Printf("[WS] 发送历史消息失败: %v", err)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -535,10 +537,22 @@ func (h *ChatHandler) HandleProactiveMessage(c *gin.Context) {
|
||||
// 检查用户是否在线
|
||||
onlineCount := h.hub.UserClientCount(req.UserID)
|
||||
if onlineCount == 0 {
|
||||
// Phase 2: 离线时排队,等待用户重连后推送
|
||||
data, _ := json.Marshal(ws.ServerMessage{
|
||||
Type: "response",
|
||||
MessageID: "proactive_" + generateID(),
|
||||
Content: req.Content,
|
||||
Role: "assistant",
|
||||
MsgType: "proactive",
|
||||
SessionID: req.SessionID,
|
||||
Timestamp: time.Now().UnixMilli(),
|
||||
})
|
||||
h.hub.QueueProactiveMessage(req.UserID, data)
|
||||
logger.Printf("[proactive] 用户离线,消息已排队: user=%s", req.UserID)
|
||||
c.JSON(http.StatusOK, gin.H{
|
||||
"success": false,
|
||||
"reason": "user_offline",
|
||||
"message": "用户不在线,消息未发送",
|
||||
"success": true,
|
||||
"reason": "queued",
|
||||
"message": "用户离线,消息已排队等待重连后推送",
|
||||
})
|
||||
return
|
||||
}
|
||||
@@ -557,7 +571,7 @@ func (h *ChatHandler) HandleProactiveMessage(c *gin.Context) {
|
||||
|
||||
data, err := json.Marshal(msg)
|
||||
if err != nil {
|
||||
log.Printf("[proactive] 序列化消息失败: %v", err)
|
||||
logger.Printf("[proactive] 序列化消息失败: %v", err)
|
||||
c.JSON(http.StatusInternalServerError, gin.H{"error": "内部错误"})
|
||||
return
|
||||
}
|
||||
@@ -577,7 +591,7 @@ func (h *ChatHandler) HandleProactiveMessage(c *gin.Context) {
|
||||
})
|
||||
h.hub.RecordMessage(sessionID, "assistant", req.Content)
|
||||
|
||||
log.Printf("[proactive] 主动消息已推送: user=%s, online=%d, content_len=%d", req.UserID, onlineCount, len(req.Content))
|
||||
logger.Printf("[proactive] 主动消息已推送: user=%s, online=%d, content_len=%d", req.UserID, onlineCount, len(req.Content))
|
||||
|
||||
c.JSON(http.StatusOK, gin.H{
|
||||
"success": true,
|
||||
|
||||
@@ -10,7 +10,7 @@ import (
|
||||
"image/jpeg"
|
||||
"image/png"
|
||||
"io"
|
||||
"log"
|
||||
"github.com/yourname/cyrene-ai/pkg/logger"
|
||||
"net/http"
|
||||
"os"
|
||||
"path/filepath"
|
||||
@@ -144,7 +144,7 @@ func (h *FileHandler) Upload(c *gin.Context) {
|
||||
dateDir := time.Now().Format("2006-01-02")
|
||||
storedDir := filepath.Join(h.uploadDir, dateDir)
|
||||
if err := os.MkdirAll(storedDir, 0755); err != nil {
|
||||
log.Printf("[FileHandler] 创建上传目录失败: %v", err)
|
||||
logger.Printf("[FileHandler] 创建上传目录失败: %v", err)
|
||||
c.JSON(http.StatusInternalServerError, gin.H{"error": "创建上传目录失败", "errorType": "server_error"})
|
||||
return
|
||||
}
|
||||
@@ -160,7 +160,7 @@ func (h *FileHandler) Upload(c *gin.Context) {
|
||||
// 保存到磁盘
|
||||
dst, err := os.Create(storedPath)
|
||||
if err != nil {
|
||||
log.Printf("[FileHandler] 创建文件失败: %v", err)
|
||||
logger.Printf("[FileHandler] 创建文件失败: %v", err)
|
||||
c.JSON(http.StatusInternalServerError, gin.H{"error": "保存文件失败", "errorType": "server_error"})
|
||||
return
|
||||
}
|
||||
@@ -169,7 +169,7 @@ func (h *FileHandler) Upload(c *gin.Context) {
|
||||
written, err := io.Copy(dst, teeReader)
|
||||
if err != nil {
|
||||
os.Remove(storedPath)
|
||||
log.Printf("[FileHandler] 写入文件失败: %v", err)
|
||||
logger.Printf("[FileHandler] 写入文件失败: %v", err)
|
||||
c.JSON(http.StatusInternalServerError, gin.H{"error": "写入文件失败", "errorType": "server_error"})
|
||||
return
|
||||
}
|
||||
@@ -180,7 +180,7 @@ func (h *FileHandler) Upload(c *gin.Context) {
|
||||
if existing, err := h.store.GetFileByHash(hash); err == nil && existing != nil {
|
||||
// 删除刚保存的重复文件
|
||||
os.Remove(storedPath)
|
||||
log.Printf("[FileHandler] 文件去重: 复用已有文件 %s (hash=%s)", existing.ID, hash[:16])
|
||||
logger.Printf("[FileHandler] 文件去重: 复用已有文件 %s (hash=%s)", existing.ID, hash[:16])
|
||||
|
||||
c.JSON(http.StatusOK, gin.H{
|
||||
"id": existing.ID,
|
||||
@@ -208,12 +208,12 @@ func (h *FileHandler) Upload(c *gin.Context) {
|
||||
|
||||
if err := h.store.CreateFile(fileRecord); err != nil {
|
||||
os.Remove(storedPath)
|
||||
log.Printf("[FileHandler] 创建文件记录失败: %v", err)
|
||||
logger.Printf("[FileHandler] 创建文件记录失败: %v", err)
|
||||
c.JSON(http.StatusInternalServerError, gin.H{"error": "创建文件记录失败", "errorType": "db_error"})
|
||||
return
|
||||
}
|
||||
|
||||
log.Printf("[FileHandler] 文件上传成功: %s (%s, %d bytes, hash=%s)", fileID, safeFilename, written, hash[:16])
|
||||
logger.Printf("[FileHandler] 文件上传成功: %s (%s, %d bytes, hash=%s)", fileID, safeFilename, written, hash[:16])
|
||||
|
||||
c.JSON(http.StatusCreated, gin.H{
|
||||
"id": fileID,
|
||||
@@ -240,7 +240,7 @@ func (h *FileHandler) List(c *gin.Context) {
|
||||
|
||||
files, total, err := h.store.GetUserFiles(userID, page, limit)
|
||||
if err != nil {
|
||||
log.Printf("[FileHandler] 查询文件列表失败: %v", err)
|
||||
logger.Printf("[FileHandler] 查询文件列表失败: %v", err)
|
||||
c.JSON(http.StatusInternalServerError, gin.H{"error": "查询文件列表失败", "errorType": "db_error"})
|
||||
return
|
||||
}
|
||||
@@ -288,7 +288,7 @@ func (h *FileHandler) Get(c *gin.Context) {
|
||||
|
||||
f, err := h.store.GetFile(fileID)
|
||||
if err != nil {
|
||||
log.Printf("[FileHandler] 查询文件失败: %v", err)
|
||||
logger.Printf("[FileHandler] 查询文件失败: %v", err)
|
||||
c.JSON(http.StatusInternalServerError, gin.H{"error": "查询文件失败", "errorType": "db_error"})
|
||||
return
|
||||
}
|
||||
@@ -338,7 +338,7 @@ func (h *FileHandler) Download(c *gin.Context) {
|
||||
|
||||
f, err := h.store.GetFile(fileID)
|
||||
if err != nil {
|
||||
log.Printf("[FileHandler] 查询文件失败: %v", err)
|
||||
logger.Printf("[FileHandler] 查询文件失败: %v", err)
|
||||
c.JSON(http.StatusInternalServerError, gin.H{"error": "查询文件失败", "errorType": "db_error"})
|
||||
return
|
||||
}
|
||||
@@ -385,7 +385,7 @@ func (h *FileHandler) Delete(c *gin.Context) {
|
||||
|
||||
f, err := h.store.GetFile(fileID)
|
||||
if err != nil {
|
||||
log.Printf("[FileHandler] 查询文件失败: %v", err)
|
||||
logger.Printf("[FileHandler] 查询文件失败: %v", err)
|
||||
c.JSON(http.StatusInternalServerError, gin.H{"error": "查询文件失败", "errorType": "db_error"})
|
||||
return
|
||||
}
|
||||
@@ -405,12 +405,12 @@ func (h *FileHandler) Delete(c *gin.Context) {
|
||||
|
||||
// 删除磁盘上的文件(忽略错误,可能已被删除)
|
||||
if err := os.Remove(f.StoredPath); err != nil && !os.IsNotExist(err) {
|
||||
log.Printf("[FileHandler] 删除磁盘文件失败 (stored_path=%s): %v", f.StoredPath, err)
|
||||
logger.Printf("[FileHandler] 删除磁盘文件失败 (stored_path=%s): %v", f.StoredPath, err)
|
||||
}
|
||||
|
||||
// 删除数据库记录
|
||||
if err := h.store.DeleteFile(fileID); err != nil {
|
||||
log.Printf("[FileHandler] 删除文件记录失败: %v", err)
|
||||
logger.Printf("[FileHandler] 删除文件记录失败: %v", err)
|
||||
c.JSON(http.StatusInternalServerError, gin.H{"error": "删除文件记录失败", "errorType": "db_error"})
|
||||
return
|
||||
}
|
||||
@@ -432,7 +432,7 @@ func (h *FileHandler) Thumbnail(c *gin.Context) {
|
||||
|
||||
f, err := h.store.GetFile(fileID)
|
||||
if err != nil {
|
||||
log.Printf("[FileHandler] 查询文件失败: %v", err)
|
||||
logger.Printf("[FileHandler] 查询文件失败: %v", err)
|
||||
c.JSON(http.StatusInternalServerError, gin.H{"error": "查询文件失败", "errorType": "db_error"})
|
||||
return
|
||||
}
|
||||
@@ -457,7 +457,7 @@ func (h *FileHandler) Thumbnail(c *gin.Context) {
|
||||
c.Data(http.StatusOK, contentType, thumbData)
|
||||
return
|
||||
} else {
|
||||
log.Printf("[FileHandler] 生成缩略图失败: %v", err)
|
||||
logger.Printf("[FileHandler] 生成缩略图失败: %v", err)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -11,7 +11,7 @@ import (
|
||||
_ "image/jpeg"
|
||||
_ "image/png"
|
||||
"io"
|
||||
"log"
|
||||
"github.com/yourname/cyrene-ai/pkg/logger"
|
||||
"net/http"
|
||||
"os"
|
||||
"sort"
|
||||
@@ -116,7 +116,7 @@ func (h *ImageHandler) analyzeByFileID(c *gin.Context, userID, fileID string) {
|
||||
|
||||
f, err := h.fileStore.GetFile(fileID)
|
||||
if err != nil {
|
||||
log.Printf("[ImageHandler] 查询文件失败: %v", err)
|
||||
logger.Printf("[ImageHandler] 查询文件失败: %v", err)
|
||||
c.JSON(http.StatusInternalServerError, gin.H{"error": "查询文件失败", "errorType": "db_error"})
|
||||
return
|
||||
}
|
||||
@@ -135,7 +135,7 @@ func (h *ImageHandler) analyzeByFileID(c *gin.Context, userID, fileID string) {
|
||||
|
||||
result, err := h.analyzeImage(f.StoredPath, f.MimeType, f.Size)
|
||||
if err != nil {
|
||||
log.Printf("[ImageHandler] 图片分析失败: %v", err)
|
||||
logger.Printf("[ImageHandler] 图片分析失败: %v", err)
|
||||
c.JSON(http.StatusInternalServerError, gin.H{"error": "图片分析失败: " + err.Error(), "errorType": "analysis_error"})
|
||||
return
|
||||
}
|
||||
@@ -192,7 +192,7 @@ func (h *ImageHandler) analyzeUploadedFile(c *gin.Context, userID string, file i
|
||||
|
||||
result, err := h.analyzeImage(tmpFile.Name(), mimeType, int64(len(data)))
|
||||
if err != nil {
|
||||
log.Printf("[ImageHandler] 图片分析失败: %v", err)
|
||||
logger.Printf("[ImageHandler] 图片分析失败: %v", err)
|
||||
c.JSON(http.StatusInternalServerError, gin.H{"error": "图片分析失败: " + err.Error(), "errorType": "analysis_error"})
|
||||
return
|
||||
}
|
||||
@@ -209,7 +209,7 @@ func (h *ImageHandler) analyzeImage(filePath, mimeType string, fileSize int64) (
|
||||
if err == nil {
|
||||
return result, nil
|
||||
}
|
||||
log.Printf("[ImageHandler] OpenAI Vision 分析失败,降级到本地分析: %v", err)
|
||||
logger.Printf("[ImageHandler] OpenAI Vision 分析失败,降级到本地分析: %v", err)
|
||||
}
|
||||
|
||||
// 降级到本地分析
|
||||
|
||||
@@ -2,7 +2,7 @@ package handler
|
||||
|
||||
import (
|
||||
"html"
|
||||
"log"
|
||||
"github.com/yourname/cyrene-ai/pkg/logger"
|
||||
"net/http"
|
||||
"os"
|
||||
"strings"
|
||||
@@ -83,7 +83,7 @@ func (h *KnowledgeHandler) CreateKB(c *gin.Context) {
|
||||
}
|
||||
|
||||
if err := h.store.CreateKB(kb); err != nil {
|
||||
log.Printf("[KnowledgeHandler] 创建知识库失败: %v", err)
|
||||
logger.Printf("[KnowledgeHandler] 创建知识库失败: %v", err)
|
||||
c.JSON(http.StatusInternalServerError, gin.H{"error": "创建知识库失败", "errorType": "db_error"})
|
||||
return
|
||||
}
|
||||
@@ -101,7 +101,7 @@ func (h *KnowledgeHandler) ListKBs(c *gin.Context) {
|
||||
|
||||
kbs, err := h.store.GetKBsByUser(userID)
|
||||
if err != nil {
|
||||
log.Printf("[KnowledgeHandler] 查询知识库列表失败: %v", err)
|
||||
logger.Printf("[KnowledgeHandler] 查询知识库列表失败: %v", err)
|
||||
c.JSON(http.StatusInternalServerError, gin.H{"error": "查询知识库列表失败", "errorType": "db_error"})
|
||||
return
|
||||
}
|
||||
@@ -120,7 +120,7 @@ func (h *KnowledgeHandler) GetKB(c *gin.Context) {
|
||||
|
||||
kb, err := h.store.GetKB(kbID)
|
||||
if err != nil {
|
||||
log.Printf("[KnowledgeHandler] 查询知识库失败: %v", err)
|
||||
logger.Printf("[KnowledgeHandler] 查询知识库失败: %v", err)
|
||||
c.JSON(http.StatusInternalServerError, gin.H{"error": "查询知识库失败", "errorType": "db_error"})
|
||||
return
|
||||
}
|
||||
@@ -136,7 +136,7 @@ func (h *KnowledgeHandler) GetKB(c *gin.Context) {
|
||||
// 获取文档列表
|
||||
docs, err := h.store.GetDocumentsByKB(kbID)
|
||||
if err != nil {
|
||||
log.Printf("[KnowledgeHandler] 查询文档列表失败: %v", err)
|
||||
logger.Printf("[KnowledgeHandler] 查询文档列表失败: %v", err)
|
||||
docs = []store.KnowledgeDocument{}
|
||||
}
|
||||
|
||||
@@ -163,7 +163,7 @@ func (h *KnowledgeHandler) UpdateKB(c *gin.Context) {
|
||||
|
||||
kb, err := h.store.GetKB(kbID)
|
||||
if err != nil {
|
||||
log.Printf("[KnowledgeHandler] 查询知识库失败: %v", err)
|
||||
logger.Printf("[KnowledgeHandler] 查询知识库失败: %v", err)
|
||||
c.JSON(http.StatusInternalServerError, gin.H{"error": "查询知识库失败", "errorType": "db_error"})
|
||||
return
|
||||
}
|
||||
@@ -177,7 +177,7 @@ func (h *KnowledgeHandler) UpdateKB(c *gin.Context) {
|
||||
}
|
||||
|
||||
if err := h.store.UpdateKB(kbID, html.EscapeString(req.Name), html.EscapeString(req.Description)); err != nil {
|
||||
log.Printf("[KnowledgeHandler] 更新知识库失败: %v", err)
|
||||
logger.Printf("[KnowledgeHandler] 更新知识库失败: %v", err)
|
||||
c.JSON(http.StatusInternalServerError, gin.H{"error": "更新知识库失败", "errorType": "db_error"})
|
||||
return
|
||||
}
|
||||
@@ -196,7 +196,7 @@ func (h *KnowledgeHandler) DeleteKB(c *gin.Context) {
|
||||
|
||||
kb, err := h.store.GetKB(kbID)
|
||||
if err != nil {
|
||||
log.Printf("[KnowledgeHandler] 查询知识库失败: %v", err)
|
||||
logger.Printf("[KnowledgeHandler] 查询知识库失败: %v", err)
|
||||
c.JSON(http.StatusInternalServerError, gin.H{"error": "查询知识库失败", "errorType": "db_error"})
|
||||
return
|
||||
}
|
||||
@@ -210,7 +210,7 @@ func (h *KnowledgeHandler) DeleteKB(c *gin.Context) {
|
||||
}
|
||||
|
||||
if err := h.store.DeleteKB(kbID); err != nil {
|
||||
log.Printf("[KnowledgeHandler] 删除知识库失败: %v", err)
|
||||
logger.Printf("[KnowledgeHandler] 删除知识库失败: %v", err)
|
||||
c.JSON(http.StatusInternalServerError, gin.H{"error": "删除知识库失败", "errorType": "db_error"})
|
||||
return
|
||||
}
|
||||
@@ -230,7 +230,7 @@ func (h *KnowledgeHandler) AddDocument(c *gin.Context) {
|
||||
// 检查知识库是否存在且属于当前用户
|
||||
kb, err := h.store.GetKB(kbID)
|
||||
if err != nil {
|
||||
log.Printf("[KnowledgeHandler] 查询知识库失败: %v", err)
|
||||
logger.Printf("[KnowledgeHandler] 查询知识库失败: %v", err)
|
||||
c.JSON(http.StatusInternalServerError, gin.H{"error": "查询知识库失败", "errorType": "db_error"})
|
||||
return
|
||||
}
|
||||
@@ -324,7 +324,7 @@ func (h *KnowledgeHandler) AddDocument(c *gin.Context) {
|
||||
}
|
||||
|
||||
if err := h.store.AddDocument(doc); err != nil {
|
||||
log.Printf("[KnowledgeHandler] 添加文档失败: %v", err)
|
||||
logger.Printf("[KnowledgeHandler] 添加文档失败: %v", err)
|
||||
c.JSON(http.StatusInternalServerError, gin.H{"error": "添加文档失败", "errorType": "db_error"})
|
||||
return
|
||||
}
|
||||
@@ -332,7 +332,7 @@ func (h *KnowledgeHandler) AddDocument(c *gin.Context) {
|
||||
// 自动分块
|
||||
chunkCount, err := h.store.ChunkDocument(doc.ID)
|
||||
if err != nil {
|
||||
log.Printf("[KnowledgeHandler] 文档分块失败: %v", err)
|
||||
logger.Printf("[KnowledgeHandler] 文档分块失败: %v", err)
|
||||
// 分块失败不影响文档创建
|
||||
}
|
||||
|
||||
@@ -353,7 +353,7 @@ func (h *KnowledgeHandler) ListDocuments(c *gin.Context) {
|
||||
// 检查权限
|
||||
kb, err := h.store.GetKB(kbID)
|
||||
if err != nil {
|
||||
log.Printf("[KnowledgeHandler] 查询知识库失败: %v", err)
|
||||
logger.Printf("[KnowledgeHandler] 查询知识库失败: %v", err)
|
||||
c.JSON(http.StatusInternalServerError, gin.H{"error": "查询知识库失败", "errorType": "db_error"})
|
||||
return
|
||||
}
|
||||
@@ -368,7 +368,7 @@ func (h *KnowledgeHandler) ListDocuments(c *gin.Context) {
|
||||
|
||||
docs, err := h.store.GetDocumentsByKB(kbID)
|
||||
if err != nil {
|
||||
log.Printf("[KnowledgeHandler] 查询文档列表失败: %v", err)
|
||||
logger.Printf("[KnowledgeHandler] 查询文档列表失败: %v", err)
|
||||
c.JSON(http.StatusInternalServerError, gin.H{"error": "查询文档列表失败", "errorType": "db_error"})
|
||||
return
|
||||
}
|
||||
@@ -387,7 +387,7 @@ func (h *KnowledgeHandler) GetDocument(c *gin.Context) {
|
||||
|
||||
doc, err := h.store.GetDocument(docID)
|
||||
if err != nil {
|
||||
log.Printf("[KnowledgeHandler] 查询文档失败: %v", err)
|
||||
logger.Printf("[KnowledgeHandler] 查询文档失败: %v", err)
|
||||
c.JSON(http.StatusInternalServerError, gin.H{"error": "查询文档失败", "errorType": "db_error"})
|
||||
return
|
||||
}
|
||||
@@ -403,7 +403,7 @@ func (h *KnowledgeHandler) GetDocument(c *gin.Context) {
|
||||
// 获取分块
|
||||
chunks, err := h.store.GetChunksByDocID(docID)
|
||||
if err != nil {
|
||||
log.Printf("[KnowledgeHandler] 查询分块失败: %v", err)
|
||||
logger.Printf("[KnowledgeHandler] 查询分块失败: %v", err)
|
||||
chunks = []store.KnowledgeChunk{}
|
||||
}
|
||||
|
||||
@@ -424,7 +424,7 @@ func (h *KnowledgeHandler) DeleteDocument(c *gin.Context) {
|
||||
|
||||
doc, err := h.store.GetDocument(docID)
|
||||
if err != nil {
|
||||
log.Printf("[KnowledgeHandler] 查询文档失败: %v", err)
|
||||
logger.Printf("[KnowledgeHandler] 查询文档失败: %v", err)
|
||||
c.JSON(http.StatusInternalServerError, gin.H{"error": "查询文档失败", "errorType": "db_error"})
|
||||
return
|
||||
}
|
||||
@@ -438,7 +438,7 @@ func (h *KnowledgeHandler) DeleteDocument(c *gin.Context) {
|
||||
}
|
||||
|
||||
if err := h.store.DeleteDocument(docID); err != nil {
|
||||
log.Printf("[KnowledgeHandler] 删除文档失败: %v", err)
|
||||
logger.Printf("[KnowledgeHandler] 删除文档失败: %v", err)
|
||||
c.JSON(http.StatusInternalServerError, gin.H{"error": "删除文档失败", "errorType": "db_error"})
|
||||
return
|
||||
}
|
||||
@@ -483,7 +483,7 @@ func (h *KnowledgeHandler) Search(c *gin.Context) {
|
||||
}
|
||||
kbResults, searchErr := h.store.SearchChunks(kbID, req.Query, req.Limit)
|
||||
if searchErr != nil {
|
||||
log.Printf("[KnowledgeHandler] 搜索知识库 %s 失败: %v", kbID, searchErr)
|
||||
logger.Printf("[KnowledgeHandler] 搜索知识库 %s 失败: %v", kbID, searchErr)
|
||||
continue
|
||||
}
|
||||
results = append(results, kbResults...)
|
||||
@@ -496,7 +496,7 @@ func (h *KnowledgeHandler) Search(c *gin.Context) {
|
||||
}
|
||||
|
||||
if err != nil {
|
||||
log.Printf("[KnowledgeHandler] 搜索失败: %v", err)
|
||||
logger.Printf("[KnowledgeHandler] 搜索失败: %v", err)
|
||||
c.JSON(http.StatusInternalServerError, gin.H{"error": "搜索失败", "errorType": "db_error"})
|
||||
return
|
||||
}
|
||||
|
||||
@@ -6,7 +6,7 @@ import (
|
||||
"fmt"
|
||||
"html"
|
||||
"io"
|
||||
"log"
|
||||
"github.com/yourname/cyrene-ai/pkg/logger"
|
||||
"net/http"
|
||||
"time"
|
||||
|
||||
@@ -65,7 +65,7 @@ func (h *MemoryHandler) Query(c *gin.Context) {
|
||||
|
||||
resp, err := h.client.Do(httpReq)
|
||||
if err != nil {
|
||||
log.Printf("[memory] Memory-Service 不可达 (Query): %v", err)
|
||||
logger.Printf("[memory] Memory-Service 不可达 (Query): %v", err)
|
||||
c.JSON(http.StatusBadGateway, gin.H{
|
||||
"error": fmt.Sprintf("Memory-Service 不可达: %v", err),
|
||||
"errorType": "memory_service_unreachable",
|
||||
@@ -97,7 +97,7 @@ func (h *MemoryHandler) List(c *gin.Context) {
|
||||
|
||||
resp, err := h.client.Get(url)
|
||||
if err != nil {
|
||||
log.Printf("[memory] Memory-Service 不可达 (List): %v", err)
|
||||
logger.Printf("[memory] Memory-Service 不可达 (List): %v", err)
|
||||
c.JSON(http.StatusBadGateway, gin.H{
|
||||
"error": fmt.Sprintf("Memory-Service 不可达: %v", err),
|
||||
"errorType": "memory_service_unreachable",
|
||||
@@ -163,7 +163,7 @@ func (h *MemoryHandler) Add(c *gin.Context) {
|
||||
|
||||
resp, err := h.client.Do(httpReq)
|
||||
if err != nil {
|
||||
log.Printf("[memory] Memory-Service 不可达 (Add): %v", err)
|
||||
logger.Printf("[memory] Memory-Service 不可达 (Add): %v", err)
|
||||
c.JSON(http.StatusBadGateway, gin.H{
|
||||
"error": fmt.Sprintf("Memory-Service 不可达: %v", err),
|
||||
"errorType": "memory_service_unreachable",
|
||||
@@ -198,7 +198,7 @@ func (h *MemoryHandler) Delete(c *gin.Context) {
|
||||
|
||||
resp, err := h.client.Do(req)
|
||||
if err != nil {
|
||||
log.Printf("[memory] Memory-Service 不可达 (Delete): %v", err)
|
||||
logger.Printf("[memory] Memory-Service 不可达 (Delete): %v", err)
|
||||
c.JSON(http.StatusBadGateway, gin.H{
|
||||
"error": fmt.Sprintf("Memory-Service 不可达: %v", err),
|
||||
"errorType": "memory_service_unreachable",
|
||||
|
||||
@@ -2,7 +2,7 @@ package handler
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"log"
|
||||
"github.com/yourname/cyrene-ai/pkg/logger"
|
||||
"net/http"
|
||||
"time"
|
||||
|
||||
@@ -54,7 +54,7 @@ func (h *NotificationHandler) Push(c *gin.Context) {
|
||||
|
||||
data, err := json.Marshal(msg)
|
||||
if err != nil {
|
||||
log.Printf("[notification] 序列化通知失败: %v", err)
|
||||
logger.Printf("[notification] 序列化通知失败: %v", err)
|
||||
c.JSON(http.StatusInternalServerError, gin.H{"error": "内部错误"})
|
||||
return
|
||||
}
|
||||
@@ -62,7 +62,7 @@ func (h *NotificationHandler) Push(c *gin.Context) {
|
||||
// 通过 Hub 推送给指定用户
|
||||
h.hub.SendToUser(req.UserID, data)
|
||||
|
||||
log.Printf("[notification] 通知已推送: user=%s type=%s title=%s", req.UserID, req.Type, req.Title)
|
||||
logger.Printf("[notification] 通知已推送: user=%s type=%s title=%s", req.UserID, req.Type, req.Title)
|
||||
|
||||
c.JSON(http.StatusOK, gin.H{
|
||||
"success": true,
|
||||
@@ -99,7 +99,7 @@ func (h *NotificationHandler) InternalNotify(c *gin.Context) {
|
||||
|
||||
data, err := json.Marshal(msg)
|
||||
if err != nil {
|
||||
log.Printf("[notification] 序列化通知失败: %v", err)
|
||||
logger.Printf("[notification] 序列化通知失败: %v", err)
|
||||
c.JSON(http.StatusInternalServerError, gin.H{"error": "内部错误"})
|
||||
return
|
||||
}
|
||||
@@ -107,7 +107,7 @@ func (h *NotificationHandler) InternalNotify(c *gin.Context) {
|
||||
// 通过 Hub 推送给指定用户
|
||||
h.hub.SendToUser(req.UserID, data)
|
||||
|
||||
log.Printf("[notification] 内部通知已推送: user=%s type=%s title=%s", req.UserID, req.Type, req.Title)
|
||||
logger.Printf("[notification] 内部通知已推送: user=%s type=%s title=%s", req.UserID, req.Type, req.Title)
|
||||
|
||||
c.JSON(http.StatusOK, gin.H{
|
||||
"success": true,
|
||||
|
||||
@@ -3,7 +3,7 @@ package handler
|
||||
import (
|
||||
"encoding/json"
|
||||
"html"
|
||||
"log"
|
||||
"github.com/yourname/cyrene-ai/pkg/logger"
|
||||
"net/http"
|
||||
"strconv"
|
||||
"time"
|
||||
@@ -71,7 +71,7 @@ func (h *ReminderHandler) List(c *gin.Context) {
|
||||
|
||||
reminders, err := h.store.GetRemindersByUser(userID, status, limit, offset)
|
||||
if err != nil {
|
||||
log.Printf("[reminder] 获取提醒列表失败: %v", err)
|
||||
logger.Printf("[reminder] 获取提醒列表失败: %v", err)
|
||||
c.JSON(http.StatusInternalServerError, gin.H{"error": "获取提醒列表失败"})
|
||||
return
|
||||
}
|
||||
@@ -124,12 +124,12 @@ func (h *ReminderHandler) Create(c *gin.Context) {
|
||||
}
|
||||
|
||||
if err := h.store.CreateReminder(reminder); err != nil {
|
||||
log.Printf("[reminder] 创建提醒失败: %v", err)
|
||||
logger.Printf("[reminder] 创建提醒失败: %v", err)
|
||||
c.JSON(http.StatusInternalServerError, gin.H{"error": "创建提醒失败"})
|
||||
return
|
||||
}
|
||||
|
||||
log.Printf("[reminder] 提醒已创建: id=%s user=%s title=%s remind_at=%s repeat=%s",
|
||||
logger.Printf("[reminder] 提醒已创建: id=%s user=%s title=%s remind_at=%s repeat=%s",
|
||||
reminder.ID, userID, reminder.Title, remindAt.Format(time.RFC3339), repeatType)
|
||||
|
||||
c.JSON(http.StatusCreated, gin.H{
|
||||
@@ -204,12 +204,12 @@ func (h *ReminderHandler) Update(c *gin.Context) {
|
||||
}
|
||||
|
||||
if err := h.store.UpdateReminder(id, existing); err != nil {
|
||||
log.Printf("[reminder] 更新提醒失败: %v", err)
|
||||
logger.Printf("[reminder] 更新提醒失败: %v", err)
|
||||
c.JSON(http.StatusInternalServerError, gin.H{"error": "更新提醒失败"})
|
||||
return
|
||||
}
|
||||
|
||||
log.Printf("[reminder] 提醒已更新: id=%s", id)
|
||||
logger.Printf("[reminder] 提醒已更新: id=%s", id)
|
||||
|
||||
c.JSON(http.StatusOK, gin.H{
|
||||
"success": true,
|
||||
@@ -227,12 +227,12 @@ func (h *ReminderHandler) Delete(c *gin.Context) {
|
||||
}
|
||||
|
||||
if err := h.store.DeleteReminder(id); err != nil {
|
||||
log.Printf("[reminder] 删除提醒失败: %v", err)
|
||||
logger.Printf("[reminder] 删除提醒失败: %v", err)
|
||||
c.JSON(http.StatusInternalServerError, gin.H{"error": "删除提醒失败"})
|
||||
return
|
||||
}
|
||||
|
||||
log.Printf("[reminder] 提醒已删除: id=%s", id)
|
||||
logger.Printf("[reminder] 提醒已删除: id=%s", id)
|
||||
|
||||
c.JSON(http.StatusOK, gin.H{
|
||||
"success": true,
|
||||
@@ -247,7 +247,7 @@ func StartReminderScheduler(s *store.ReminderStore, hub *ws.Hub) {
|
||||
ticker := time.NewTicker(30 * time.Second)
|
||||
defer ticker.Stop()
|
||||
|
||||
log.Println("[ReminderScheduler] 提醒调度器已启动 (检查间隔: 30秒)")
|
||||
logger.Println("[ReminderScheduler] 提醒调度器已启动 (检查间隔: 30秒)")
|
||||
|
||||
for range ticker.C {
|
||||
checkAndNotify(s, hub)
|
||||
@@ -259,7 +259,7 @@ func StartReminderScheduler(s *store.ReminderStore, hub *ws.Hub) {
|
||||
func checkAndNotify(s *store.ReminderStore, hub *ws.Hub) {
|
||||
reminders, err := s.GetDueReminders()
|
||||
if err != nil {
|
||||
log.Printf("[ReminderScheduler] 获取到期提醒失败: %v", err)
|
||||
logger.Printf("[ReminderScheduler] 获取到期提醒失败: %v", err)
|
||||
return
|
||||
}
|
||||
|
||||
@@ -290,7 +290,7 @@ func checkAndNotify(s *store.ReminderStore, hub *ws.Hub) {
|
||||
|
||||
data, err := json.Marshal(msg)
|
||||
if err != nil {
|
||||
log.Printf("[ReminderScheduler] 序列化通知失败: %v", err)
|
||||
logger.Printf("[ReminderScheduler] 序列化通知失败: %v", err)
|
||||
continue
|
||||
}
|
||||
|
||||
@@ -299,7 +299,7 @@ func checkAndNotify(s *store.ReminderStore, hub *ws.Hub) {
|
||||
|
||||
// 3. 标记为已通知
|
||||
if err := s.MarkNotified(r.ID); err != nil {
|
||||
log.Printf("[ReminderScheduler] 标记已通知失败: id=%s err=%v", r.ID, err)
|
||||
logger.Printf("[ReminderScheduler] 标记已通知失败: id=%s err=%v", r.ID, err)
|
||||
}
|
||||
|
||||
// 4. 处理重复提醒
|
||||
@@ -308,9 +308,9 @@ func checkAndNotify(s *store.ReminderStore, hub *ws.Hub) {
|
||||
r.RemindAt = nextTime
|
||||
r.Notified = false
|
||||
if err := s.UpdateReminder(r.ID, &r); err != nil {
|
||||
log.Printf("[ReminderScheduler] 更新重复提醒失败: id=%s err=%v", r.ID, err)
|
||||
logger.Printf("[ReminderScheduler] 更新重复提醒失败: id=%s err=%v", r.ID, err)
|
||||
} else {
|
||||
log.Printf("[ReminderScheduler] 重复提醒已更新: id=%s next=%s", r.ID, nextTime.Format(time.RFC3339))
|
||||
logger.Printf("[ReminderScheduler] 重复提醒已更新: id=%s next=%s", r.ID, nextTime.Format(time.RFC3339))
|
||||
}
|
||||
} else {
|
||||
// 非重复提醒:标记为已完成
|
||||
@@ -318,11 +318,11 @@ func checkAndNotify(s *store.ReminderStore, hub *ws.Hub) {
|
||||
r.Status = "completed"
|
||||
r.CompletedAt = &now
|
||||
if err := s.UpdateReminder(r.ID, &r); err != nil {
|
||||
log.Printf("[ReminderScheduler] 标记提醒完成失败: id=%s err=%v", r.ID, err)
|
||||
logger.Printf("[ReminderScheduler] 标记提醒完成失败: id=%s err=%v", r.ID, err)
|
||||
}
|
||||
}
|
||||
|
||||
log.Printf("[ReminderScheduler] 提醒已推送: user=%s title=%s id=%s", r.UserID, r.Title, r.ID)
|
||||
logger.Printf("[ReminderScheduler] 提醒已推送: user=%s title=%s id=%s", r.UserID, r.Title, r.ID)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -4,7 +4,7 @@ import (
|
||||
"crypto/rand"
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"log"
|
||||
"github.com/yourname/cyrene-ai/pkg/logger"
|
||||
"net/http"
|
||||
"strings"
|
||||
"time"
|
||||
@@ -68,7 +68,7 @@ func (h *SessionHandler) Create(c *gin.Context) {
|
||||
|
||||
if h.useDB {
|
||||
if err := h.store.CreateSession(userID, req.SessionID, req.Title, req.IsMain); err != nil {
|
||||
log.Printf("[SessionHandler] 创建会话失败: %v", err)
|
||||
logger.Printf("[SessionHandler] 创建会话失败: %v", err)
|
||||
c.JSON(http.StatusInternalServerError, gin.H{"error": "创建会话失败", "errorType": "db_error"})
|
||||
return
|
||||
}
|
||||
@@ -106,7 +106,7 @@ func (h *SessionHandler) List(c *gin.Context) {
|
||||
if h.useDB {
|
||||
sessions, err := h.store.GetUserSessions(userID)
|
||||
if err != nil {
|
||||
log.Printf("[SessionHandler] 查询会话列表失败: %v", err)
|
||||
logger.Printf("[SessionHandler] 查询会话列表失败: %v", err)
|
||||
c.JSON(http.StatusInternalServerError, gin.H{"error": "查询会话失败", "errorType": "db_error"})
|
||||
return
|
||||
}
|
||||
@@ -139,7 +139,7 @@ func (h *SessionHandler) Get(c *gin.Context) {
|
||||
if h.useDB {
|
||||
session, err := h.store.GetSession(sessionID)
|
||||
if err != nil {
|
||||
log.Printf("[SessionHandler] 查询会话失败: %v", err)
|
||||
logger.Printf("[SessionHandler] 查询会话失败: %v", err)
|
||||
c.JSON(http.StatusInternalServerError, gin.H{"error": "查询会话失败", "errorType": "db_error"})
|
||||
return
|
||||
}
|
||||
@@ -186,7 +186,7 @@ func (h *SessionHandler) Delete(c *gin.Context) {
|
||||
// 所有权校验:先获取session再验证归属
|
||||
session, err := h.store.GetSession(sessionID)
|
||||
if err != nil {
|
||||
log.Printf("[SessionHandler] 查询会话失败: %v", err)
|
||||
logger.Printf("[SessionHandler] 查询会话失败: %v", err)
|
||||
c.JSON(http.StatusInternalServerError, gin.H{"error": "删除会话失败", "errorType": "db_error"})
|
||||
return
|
||||
}
|
||||
@@ -203,7 +203,7 @@ func (h *SessionHandler) Delete(c *gin.Context) {
|
||||
}
|
||||
|
||||
if err := h.store.DeleteSession(sessionID); err != nil {
|
||||
log.Printf("[SessionHandler] 删除会话失败: %v", err)
|
||||
logger.Printf("[SessionHandler] 删除会话失败: %v", err)
|
||||
c.JSON(http.StatusInternalServerError, gin.H{"error": "删除会话失败", "errorType": "db_error"})
|
||||
return
|
||||
}
|
||||
@@ -235,7 +235,7 @@ func (h *SessionHandler) DeleteAll(c *gin.Context) {
|
||||
|
||||
if h.useDB {
|
||||
if err := h.store.DeleteAllUserSessions(userID); err != nil {
|
||||
log.Printf("[SessionHandler] 删除用户所有会话失败: %v", err)
|
||||
logger.Printf("[SessionHandler] 删除用户所有会话失败: %v", err)
|
||||
c.JSON(http.StatusInternalServerError, gin.H{"error": "删除会话失败", "errorType": "db_error"})
|
||||
return
|
||||
}
|
||||
@@ -254,7 +254,7 @@ func (h *SessionHandler) GetMessages(c *gin.Context) {
|
||||
if h.useDB {
|
||||
session, err := h.store.GetSession(sessionID)
|
||||
if err != nil {
|
||||
log.Printf("[SessionHandler] 查询会话失败: %v", err)
|
||||
logger.Printf("[SessionHandler] 查询会话失败: %v", err)
|
||||
c.JSON(http.StatusInternalServerError, gin.H{"error": "查询消息失败", "errorType": "db_error"})
|
||||
return
|
||||
}
|
||||
@@ -302,7 +302,7 @@ func (h *SessionHandler) GetMessages(c *gin.Context) {
|
||||
if h.useDB {
|
||||
messages, err := h.store.GetMessages(sessionID, limit, offset)
|
||||
if err != nil {
|
||||
log.Printf("[SessionHandler] 查询消息失败: %v", err)
|
||||
logger.Printf("[SessionHandler] 查询消息失败: %v", err)
|
||||
c.JSON(http.StatusInternalServerError, gin.H{"error": "查询消息失败", "errorType": "db_error"})
|
||||
return
|
||||
}
|
||||
@@ -313,6 +313,7 @@ func (h *SessionHandler) GetMessages(c *gin.Context) {
|
||||
"id": m.ID,
|
||||
"session_id": m.SessionID,
|
||||
"role": m.Role,
|
||||
"msg_type": m.MsgType,
|
||||
"content": m.Content,
|
||||
"created_at": m.CreatedAt.UnixMilli(),
|
||||
})
|
||||
@@ -339,7 +340,7 @@ func (h *SessionHandler) ClearMessages(c *gin.Context) {
|
||||
// 所有权校验
|
||||
session, err := h.store.GetSession(sessionID)
|
||||
if err != nil {
|
||||
log.Printf("[SessionHandler] 查询会话失败: %v", err)
|
||||
logger.Printf("[SessionHandler] 查询会话失败: %v", err)
|
||||
c.JSON(http.StatusInternalServerError, gin.H{"error": "清空消息失败", "errorType": "db_error"})
|
||||
return
|
||||
}
|
||||
@@ -356,7 +357,7 @@ func (h *SessionHandler) ClearMessages(c *gin.Context) {
|
||||
}
|
||||
|
||||
if err := h.store.ClearSessionMessages(sessionID); err != nil {
|
||||
log.Printf("[SessionHandler] 清空消息失败: %v", err)
|
||||
logger.Printf("[SessionHandler] 清空消息失败: %v", err)
|
||||
c.JSON(http.StatusInternalServerError, gin.H{"error": "清空消息失败", "errorType": "db_error"})
|
||||
return
|
||||
}
|
||||
@@ -469,7 +470,7 @@ func (h *SessionHandler) SearchMessages(c *gin.Context) {
|
||||
|
||||
results, total, err := h.store.SearchMessages(userID, query, limit, offset)
|
||||
if err != nil {
|
||||
log.Printf("[SessionHandler] 搜索消息失败: %v", err)
|
||||
logger.Printf("[SessionHandler] 搜索消息失败: %v", err)
|
||||
c.JSON(http.StatusInternalServerError, gin.H{"error": "搜索失败", "errorType": "db_error"})
|
||||
return
|
||||
}
|
||||
@@ -531,7 +532,7 @@ func (h *SessionHandler) ExportSession(c *gin.Context) {
|
||||
// 获取会话信息
|
||||
session, err := h.store.GetSession(sessionID)
|
||||
if err != nil {
|
||||
log.Printf("[SessionHandler] 查询会话失败: %v", err)
|
||||
logger.Printf("[SessionHandler] 查询会话失败: %v", err)
|
||||
c.JSON(http.StatusInternalServerError, gin.H{"error": "查询会话失败", "errorType": "db_error"})
|
||||
return
|
||||
}
|
||||
@@ -552,7 +553,7 @@ func (h *SessionHandler) ExportSession(c *gin.Context) {
|
||||
// 获取所有消息 (不限制数量,导出全部)
|
||||
messages, err := h.store.GetMessages(sessionID, 0, 0)
|
||||
if err != nil {
|
||||
log.Printf("[SessionHandler] 查询消息失败: %v", err)
|
||||
logger.Printf("[SessionHandler] 查询消息失败: %v", err)
|
||||
c.JSON(http.StatusInternalServerError, gin.H{"error": "查询消息失败", "errorType": "db_error"})
|
||||
return
|
||||
}
|
||||
@@ -613,7 +614,7 @@ func (h *SessionHandler) exportJSON(c *gin.Context, session *store.Session, mess
|
||||
|
||||
jsonBytes, err := json.MarshalIndent(data, "", " ")
|
||||
if err != nil {
|
||||
log.Printf("[SessionHandler] JSON序列化失败: %v", err)
|
||||
logger.Printf("[SessionHandler] JSON序列化失败: %v", err)
|
||||
c.JSON(http.StatusInternalServerError, gin.H{"error": "导出失败", "errorType": "serialization_error"})
|
||||
return
|
||||
}
|
||||
|
||||
@@ -4,7 +4,7 @@ import (
|
||||
"bytes"
|
||||
"encoding/json"
|
||||
"io"
|
||||
"log"
|
||||
"github.com/yourname/cyrene-ai/pkg/logger"
|
||||
"net/http"
|
||||
"strings"
|
||||
|
||||
@@ -50,7 +50,7 @@ func (h *VoiceHandler) Transcribe(c *gin.Context) {
|
||||
|
||||
resp, err := h.client.Do(proxyReq)
|
||||
if err != nil {
|
||||
log.Printf("[voice] Voice-Service 不可达 (Transcribe): %v", err)
|
||||
logger.Printf("[voice] Voice-Service 不可达 (Transcribe): %v", err)
|
||||
c.JSON(http.StatusBadGateway, gin.H{
|
||||
"error": "Voice-Service 不可达: " + err.Error(),
|
||||
"errorType": "voice_service_unreachable",
|
||||
@@ -88,7 +88,7 @@ func (h *VoiceHandler) TTSSynthesize(c *gin.Context) {
|
||||
|
||||
resp, err := h.client.Do(proxyReq)
|
||||
if err != nil {
|
||||
log.Printf("[voice] Voice-Service 不可达 (TTS): %v", err)
|
||||
logger.Printf("[voice] Voice-Service 不可达 (TTS): %v", err)
|
||||
c.JSON(http.StatusBadGateway, gin.H{
|
||||
"error": "Voice-Service 不可达: " + err.Error(),
|
||||
"errorType": "voice_service_unreachable",
|
||||
@@ -115,7 +115,7 @@ func (h *VoiceHandler) TTSVoices(c *gin.Context) {
|
||||
|
||||
resp, err := h.client.Get(url)
|
||||
if err != nil {
|
||||
log.Printf("[voice] Voice-Service 不可达 (Voices): %v", err)
|
||||
logger.Printf("[voice] Voice-Service 不可达 (Voices): %v", err)
|
||||
c.JSON(http.StatusBadGateway, gin.H{
|
||||
"error": "Voice-Service 不可达: " + err.Error(),
|
||||
"errorType": "voice_service_unreachable",
|
||||
@@ -139,7 +139,7 @@ func (h *VoiceHandler) TTSStatus(c *gin.Context) {
|
||||
|
||||
resp, err := h.client.Get(url)
|
||||
if err != nil {
|
||||
log.Printf("[voice] Voice-Service 不可达 (TTS Status): %v", err)
|
||||
logger.Printf("[voice] Voice-Service 不可达 (TTS Status): %v", err)
|
||||
c.JSON(http.StatusBadGateway, gin.H{
|
||||
"error": "Voice-Service 不可达: " + err.Error(),
|
||||
"errorType": "voice_service_unreachable",
|
||||
@@ -162,7 +162,7 @@ func (h *VoiceHandler) VoiceStatus(c *gin.Context) {
|
||||
|
||||
resp, err := h.client.Get(url)
|
||||
if err != nil {
|
||||
log.Printf("[voice] Voice-Service 不可达 (Status): %v", err)
|
||||
logger.Printf("[voice] Voice-Service 不可达 (Status): %v", err)
|
||||
c.JSON(http.StatusBadGateway, gin.H{
|
||||
"error": "Voice-Service 不可达: " + err.Error(),
|
||||
"errorType": "voice_service_unreachable",
|
||||
|
||||
@@ -8,7 +8,7 @@ import (
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"io"
|
||||
"log"
|
||||
"github.com/yourname/cyrene-ai/pkg/logger"
|
||||
"net/http"
|
||||
"strings"
|
||||
"time"
|
||||
@@ -95,7 +95,7 @@ func (h *WebhookHandler) HandleGenericWebhook(c *gin.Context) {
|
||||
// 调用 AI-Core 获取回复
|
||||
resp, err := h.callAICore(userID, sessionID, req.Message, mode, platform)
|
||||
if err != nil {
|
||||
log.Printf("[webhook] AI-Core 调用失败 (platform=%s): %v", platform, err)
|
||||
logger.Printf("[webhook] AI-Core 调用失败 (platform=%s): %v", platform, err)
|
||||
c.JSON(502, GenericWebhookResponse{Error: "AI 服务暂不可用: " + err.Error()})
|
||||
return
|
||||
}
|
||||
@@ -244,7 +244,7 @@ func (h *WebhookHandler) HandleDiscordWebhook(c *gin.Context) {
|
||||
// 但这里简化处理:直接同步调用 AI-Core(如果调用超过 3 秒,Discord 会显示超时)
|
||||
resp, err := h.callAICore("ext_"+userID, sessionID, message, "text", "discord")
|
||||
if err != nil {
|
||||
log.Printf("[webhook:discord] AI-Core 调用失败: %v", err)
|
||||
logger.Printf("[webhook:discord] AI-Core 调用失败: %v", err)
|
||||
c.JSON(200, DiscordResponse{
|
||||
Type: 4,
|
||||
Data: &DiscordResponseData{Content: "昔涟暂时无法回应喵...(AI 服务异常: " + err.Error() + ")"},
|
||||
|
||||
Reference in New Issue
Block a user