Assist handles terminal assistance requests.
(w http.ResponseWriter, r *http.Request)
| 241 | |
| 242 | // Assist handles terminal assistance requests. |
| 243 | func (h *AIHandler) Assist(w http.ResponseWriter, r *http.Request) { |
| 244 | userID, _ := r.Context().Value(middleware.UserIDKey).(string) |
| 245 | if !h.checkRateLimit(r.Context(), userID) { |
| 246 | Error(w, http.StatusTooManyRequests, "Rate limit exceeded. Please wait a moment.") |
| 247 | return |
| 248 | } |
| 249 | |
| 250 | s, err := h.settings.GetFirst(r.Context()) |
| 251 | if err != nil { |
| 252 | Error(w, http.StatusInternalServerError, "Failed to load settings") |
| 253 | return |
| 254 | } |
| 255 | if !s.AiEnabled { |
| 256 | Error(w, http.StatusBadRequest, "AI assistant is not enabled") |
| 257 | return |
| 258 | } |
| 259 | if s.AiAPIKey == nil || *s.AiAPIKey == "" { |
| 260 | Error(w, http.StatusBadRequest, "AI API key not configured") |
| 261 | return |
| 262 | } |
| 263 | |
| 264 | var req AssistRequest |
| 265 | if err := decodeJSON(r, &req); err != nil { |
| 266 | Error(w, http.StatusBadRequest, "Invalid request body") |
| 267 | return |
| 268 | } |
| 269 | req.Question = strings.TrimSpace(req.Question) |
| 270 | if len(req.Question) < 1 || len(req.Question) > 2000 { |
| 271 | Error(w, http.StatusBadRequest, "question must be 1-2000 characters") |
| 272 | return |
| 273 | } |
| 274 | if len(req.Context) > 10000 { |
| 275 | req.Context = req.Context[:10000] |
| 276 | } |
| 277 | |
| 278 | // Sanitize history: last 10 messages, role+content required, max 2000 chars each |
| 279 | sanitized := make([]ai.Message, 0, 10) |
| 280 | start := len(req.History) - 10 |
| 281 | if start < 0 { |
| 282 | start = 0 |
| 283 | } |
| 284 | for i := start; i < len(req.History) && len(sanitized) < 10; i++ { |
| 285 | m := req.History[i] |
| 286 | if m.Role == "" || m.Content == "" { |
| 287 | continue |
| 288 | } |
| 289 | role := "user" |
| 290 | if m.Role == "assistant" { |
| 291 | role = "assistant" |
| 292 | } |
| 293 | content := m.Content |
| 294 | if len(content) > 2000 { |
| 295 | content = content[:2000] |
| 296 | } |
| 297 | sanitized = append(sanitized, ai.Message{Role: role, Content: content}) |
| 298 | } |
| 299 | |
| 300 | response, err := h.aiSvc.GetAssistance(s, req.Question, req.Context, sanitized) |
nothing calls this directly
no test coverage detected