feat: a new chat is named by the model in two or three words, asked aside; the machine's name gets its room in the chat's header

This commit is contained in:
redtea committed 2026-10-16 11:23:52 +03:00
1 parent 6442c39360
commit 80ed7d4ffa
4 files changed
+90 -3

No files matched your search

+45
View File
@@ -10,6 +10,7 @@ import (
"errors"
"fmt"
"io"
"log"
"net/http"
"strconv"
"strings"
@@ -537,8 +538,13 @@ func (s *Server) handleAIChat(w http.ResponseWriter, r *http.Request) {
in.Chat = s.aiNewChat(a.ID)
}
w.Header().Set("X-Chat-Id", strconv.FormatInt(in.Chat, 10))
fresh := in.Message != "" && len(s.aiHistoryOf(a.ID, in.Chat, 1)) == 0
s.aiAppendTo(a.ID, in.Chat, "result", in.Result)
s.aiAppendTo(a.ID, in.Chat, "user", in.Message)
if fresh {
// A new chat gets a short name from the model, aside.
go s.aiNameChat(a.ID, in.Chat, in.Message)
}
msgs := aiWindow(s.aiHistoryOf(a.ID, in.Chat, 60), 24000)
if len(in.Context) > 30000 {
in.Context = utf8Safe(in.Context[len(in.Context)-30000:])
@@ -598,6 +604,45 @@ func (s *Server) handleAIChat(w http.ResponseWriter, r *http.Request) {
}
}
// aiNameChat asks the model for a two-or-three-word name of the chat its
// first question opened, and gives the chat that name.
func (s *Server) aiNameChat(owner, chat int64, question string) {
ctx, cancel := context.WithTimeout(context.Background(), 90*time.Second)
defer cancel()
if r := []rune(question); len(r) > 600 {
question = string(r[:600])
}
var b strings.Builder
err := aiStream(ctx, s.aiConfig(), "Придумай короткое название чата по первому вопросу пользователя: 2-3 слова, по-русски, "+
"без кавычек и точки в конце. Ответь только названием.", []aiMsg{{Role: "user", Content: question}}, func(t string) { b.WriteString(t) })
if err != nil {
log.Printf("ai: naming chat %d: %v", chat, err)
return
}
if t := chatTitle(b.String()); t != "" {
_, _ = s.db.sql.Exec(`UPDATE ai_chats SET title = ? WHERE id = ? AND admin_id = ?`, t, chat, owner)
}
}
// chatTitle tidies what the model gave for a name: the first line, no
// thinking, quotes or end mark, four words at most.
func chatTitle(s string) string {
s = stripThink(s)
if i := strings.IndexByte(strings.TrimSpace(s), '\n'); i >= 0 {
s = strings.TrimSpace(s)[:i]
}
s = strings.Trim(strings.TrimSpace(s), "\"'«»„“”`*#.!:;")
w := strings.Fields(s)
if len(w) > 4 {
w = w[:4]
}
s = strings.Join(w, " ")
if r := []rune(s); len(r) > 40 {
s = string(r[:40])
}
return s
}
// GET /api/panel/ai/chats - the user's chats, newest first.
func (s *Server) handleAIChats(w http.ResponseWriter, r *http.Request) {
a := s.currentAdmin(r)