package server import ( "encoding/json" "net/http" "strconv" "strings" "chat-agent-system/internal/ctxmgr" ) // handleChatSearch 处理消息三模检索 (keyword/fuzzy/semantic/hybrid) // GET /api/v1/chat/search?session_id=&q=&mode=&category=&date_from=&date_to=&limit=&user_id= func (s *Server) handleChatSearch(w http.ResponseWriter, r *http.Request) { if r.Method != http.MethodGet { http.Error(w, "Method Not Allowed", http.StatusMethodNotAllowed) return } user, ok := s.requireAuthenticatedUser(w, r) if !ok { return } if s.svc == nil || s.svc.ContextManager() == nil { http.Error(w, "context manager not initialized", http.StatusServiceUnavailable) return } sessionID := strings.TrimSpace(r.URL.Query().Get("session_id")) if sessionID == "" { http.Error(w, "missing required query param 'session_id'", http.StatusBadRequest) return } authCtx, ok := s.authorizeSessionRead(w, r, sessionID, user) if !ok { return } query := strings.TrimSpace(r.URL.Query().Get("q")) if query == "" { http.Error(w, "missing or empty query param 'q'", http.StatusBadRequest) return } mode := ctxmgr.ChatSearchMode(strings.TrimSpace(r.URL.Query().Get("mode"))) category := strings.TrimSpace(r.URL.Query().Get("category")) dateFrom := strings.TrimSpace(r.URL.Query().Get("date_from")) dateTo := strings.TrimSpace(r.URL.Query().Get("date_to")) limit := 50 if limStr := r.URL.Query().Get("limit"); limStr != "" { if val, err := strconv.Atoi(limStr); err == nil && val > 0 { limit = val } } searchQuery := ctxmgr.ChatSearchQuery{ SessionID: sessionID, UserID: user.ID, Query: query, Mode: mode, Category: category, DateFrom: dateFrom, DateTo: dateTo, Limit: limit, } hits, err := s.svc.ContextManager().SearchChatMessages(r.Context(), searchQuery) if err != nil { http.Error(w, "SearchChatMessages error: "+err.Error(), http.StatusInternalServerError) return } hits = s.filterChatSearchHitsByAuth(authCtx, hits) if hits == nil { hits = []ctxmgr.ChatSearchHit{} } w.Header().Set("Content-Type", "application/json") _ = json.NewEncoder(w).Encode(hits) }