Apply session ownership plus scope_kind visibility across window, day, search, dates, categories, unread, and digest endpoints; add PG refresh regression test for pre-activation and task-scoped messages. Co-authored-by: Cursor <cursoragent@cursor.com>
85 lines
2.1 KiB
Go
85 lines
2.1 KiB
Go
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)
|
|
}
|