Files
story/internal/httpapi/memory_tool_handler.go
2026-08-29 21:56:51 +08:00

65 lines
2.7 KiB
Go

package httpapi
import (
"encoding/json"
"errors"
"log/slog"
"net/http"
"strings"
"data-terminal-cloud/internal/memorytool"
)
func MemoryToolSearchHandler(service *memorytool.Service, signer *memorytool.TokenSigner, limiter RateLimiter, logger *slog.Logger) http.Handler {
if logger == nil {
logger = slog.Default()
}
return http.HandlerFunc(func(writer http.ResponseWriter, request *http.Request) {
authorization := strings.TrimSpace(request.Header.Get("Authorization"))
if !strings.HasPrefix(authorization, "Bearer ") {
WriteError(writer, request, http.StatusUnauthorized, "MEMORY_TOOL_AUTHENTICATION_FAILED", "记忆工具身份验证失败")
return
}
claims, err := signer.Verify(strings.TrimSpace(strings.TrimPrefix(authorization, "Bearer ")))
if err != nil {
WriteError(writer, request, http.StatusUnauthorized, "MEMORY_TOOL_AUTHENTICATION_FAILED", "记忆工具身份验证失败")
return
}
if limiter != nil && !allowScopes(writer, request, logger, limiter, [][2]string{{"memory_tool", claims.ConversationID}}) {
return
}
decoder := json.NewDecoder(request.Body)
decoder.DisallowUnknownFields()
var input struct {
Query string `json:"query"`
Limit int `json:"limit"`
}
if err := decoder.Decode(&input); err != nil || ensureJSONEOF(decoder) != nil {
WriteError(writer, request, http.StatusBadRequest, "MEMORY_TOOL_INVALID_REQUEST", "记忆检索参数不正确")
return
}
input.Query = strings.TrimSpace(input.Query)
if input.Limit == 0 {
input.Limit = 3
}
if input.Query == "" || len([]rune(input.Query)) > 500 || input.Limit < 1 || input.Limit > 5 {
WriteError(writer, request, http.StatusBadRequest, "MEMORY_TOOL_INVALID_REQUEST", "记忆检索参数不正确")
return
}
result, err := service.Search(request.Context(), claims, input.Query, input.Limit, RequestID(request.Context()))
if err != nil {
switch {
case errors.Is(err, memorytool.ErrConversationUnavailable):
WriteError(writer, request, http.StatusConflict, "MEMORY_TOOL_CONVERSATION_UNAVAILABLE", "本次通话当前不能使用记忆检索")
case errors.Is(err, memorytool.ErrEngineModeUnsupported):
WriteError(writer, request, http.StatusConflict, "MEMORY_TOOL_ENGINE_MODE_UNSUPPORTED", "本次语音处理方式未启用通话内记忆工具")
default:
slog.ErrorContext(request.Context(), "memory tool search failed", "conversation_id", claims.ConversationID, "error", err)
WriteAPIError(writer, request, http.StatusServiceUnavailable, Error{Code: "MEMORY_TOOL_UNAVAILABLE", Message: "记忆检索暂时不可用,请继续普通交流", Retryable: true})
}
return
}
WriteJSON(writer, request, http.StatusOK, result)
})
}