16b05476a1
CI / docker (push) Failing after 1m54s
引入用户端对话/生图与管理端 Provider 配置,统一 invoke 编排、Gateway、请求日志与模型管理;前端按设计规范拆分布局,Go module 更名为 github.com/rose_cat707/Atlas;生图长任务 SSE 推送;管理端登录防爆破;协议与服务类型联动;Replicate 模型同步修复;用户端创作台 UI 重构;管理端创作历史替代请求日志。 Co-authored-by: Cursor <cursoragent@cursor.com>
141 lines
4.5 KiB
Go
141 lines
4.5 KiB
Go
package store
|
|
|
|
import "context"
|
|
|
|
type Conversation struct {
|
|
ID int64 `json:"id"`
|
|
SessionID string `json:"session_id"`
|
|
Title string `json:"title"`
|
|
Model string `json:"model"`
|
|
ParamsJSON string `json:"params_json"`
|
|
CreatedAt string `json:"created_at"`
|
|
UpdatedAt string `json:"updated_at"`
|
|
}
|
|
|
|
type ChatMessageRow struct {
|
|
ID int64 `json:"id"`
|
|
ConversationID int64 `json:"conversation_id"`
|
|
Role string `json:"role"`
|
|
Content string `json:"content"`
|
|
CreatedAt string `json:"created_at"`
|
|
}
|
|
|
|
func (s *Store) ListConversations(ctx context.Context, sessionID string) ([]Conversation, error) {
|
|
_ = s.PurgeEmptyConversations(ctx, sessionID)
|
|
rows, err := s.db.QueryContext(ctx,
|
|
`SELECT c.id, c.session_id, c.title, c.model, c.params_json, c.created_at, c.updated_at
|
|
FROM chat_conversations c
|
|
WHERE c.session_id = ?
|
|
AND EXISTS (SELECT 1 FROM chat_messages m WHERE m.conversation_id = c.id)
|
|
ORDER BY c.updated_at DESC`, sessionID,
|
|
)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
defer rows.Close()
|
|
var items []Conversation
|
|
for rows.Next() {
|
|
var c Conversation
|
|
if err := rows.Scan(&c.ID, &c.SessionID, &c.Title, &c.Model, &c.ParamsJSON, &c.CreatedAt, &c.UpdatedAt); err != nil {
|
|
return nil, err
|
|
}
|
|
items = append(items, c)
|
|
}
|
|
return items, rows.Err()
|
|
}
|
|
|
|
func (s *Store) GetConversation(ctx context.Context, sessionID string, id int64) (*Conversation, error) {
|
|
var c Conversation
|
|
err := s.db.QueryRowContext(ctx,
|
|
`SELECT id, session_id, title, model, params_json, created_at, updated_at FROM chat_conversations WHERE id = ? AND session_id = ?`, id, sessionID,
|
|
).Scan(&c.ID, &c.SessionID, &c.Title, &c.Model, &c.ParamsJSON, &c.CreatedAt, &c.UpdatedAt)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
return &c, nil
|
|
}
|
|
|
|
func (s *Store) CreateConversation(ctx context.Context, c *Conversation) (int64, error) {
|
|
res, err := s.db.ExecContext(ctx,
|
|
`INSERT INTO chat_conversations (session_id, title, model, params_json) VALUES (?, ?, ?, ?)`,
|
|
c.SessionID, c.Title, c.Model, c.ParamsJSON,
|
|
)
|
|
if err != nil {
|
|
return 0, err
|
|
}
|
|
return res.LastInsertId()
|
|
}
|
|
|
|
func (s *Store) UpdateConversation(ctx context.Context, c *Conversation) error {
|
|
_, err := s.db.ExecContext(ctx,
|
|
`UPDATE chat_conversations SET title=?, model=?, params_json=?, updated_at=datetime('now') WHERE id=? AND session_id=?`,
|
|
c.Title, c.Model, c.ParamsJSON, c.ID, c.SessionID,
|
|
)
|
|
return err
|
|
}
|
|
|
|
func (s *Store) DeleteConversation(ctx context.Context, sessionID string, id int64) error {
|
|
_, err := s.db.ExecContext(ctx, `DELETE FROM chat_conversations WHERE id = ? AND session_id = ?`, id, sessionID)
|
|
return err
|
|
}
|
|
|
|
func (s *Store) PurgeEmptyConversations(ctx context.Context, sessionID string) error {
|
|
_, err := s.db.ExecContext(ctx,
|
|
`DELETE FROM chat_conversations
|
|
WHERE session_id = ?
|
|
AND NOT EXISTS (SELECT 1 FROM chat_messages m WHERE m.conversation_id = chat_conversations.id)`,
|
|
sessionID,
|
|
)
|
|
return err
|
|
}
|
|
|
|
func (s *Store) ListMessages(ctx context.Context, conversationID int64, limit int) ([]ChatMessageRow, error) {
|
|
if limit <= 0 {
|
|
limit = 80
|
|
}
|
|
rows, err := s.db.QueryContext(ctx,
|
|
`SELECT id, conversation_id, role, content, created_at FROM chat_messages WHERE conversation_id = ? ORDER BY id DESC LIMIT ?`, conversationID, limit,
|
|
)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
defer rows.Close()
|
|
var items []ChatMessageRow
|
|
for rows.Next() {
|
|
var m ChatMessageRow
|
|
if err := rows.Scan(&m.ID, &m.ConversationID, &m.Role, &m.Content, &m.CreatedAt); err != nil {
|
|
return nil, err
|
|
}
|
|
items = append(items, m)
|
|
}
|
|
for i, j := 0, len(items)-1; i < j; i, j = i+1, j-1 {
|
|
items[i], items[j] = items[j], items[i]
|
|
}
|
|
return items, rows.Err()
|
|
}
|
|
|
|
func (s *Store) InsertMessage(ctx context.Context, m *ChatMessageRow) (int64, error) {
|
|
res, err := s.db.ExecContext(ctx,
|
|
`INSERT INTO chat_messages (conversation_id, role, content) VALUES (?, ?, ?)`,
|
|
m.ConversationID, m.Role, m.Content,
|
|
)
|
|
if err != nil {
|
|
return 0, err
|
|
}
|
|
_, _ = s.db.ExecContext(ctx, `UPDATE chat_conversations SET updated_at=datetime('now') WHERE id=?`, m.ConversationID)
|
|
return res.LastInsertId()
|
|
}
|
|
|
|
func (s *Store) CountUserMessages(ctx context.Context, conversationID int64) (int, error) {
|
|
var count int
|
|
err := s.db.QueryRowContext(ctx,
|
|
`SELECT COUNT(*) FROM chat_messages WHERE conversation_id = ? AND role = 'user'`, conversationID,
|
|
).Scan(&count)
|
|
return count, err
|
|
}
|
|
|
|
func (s *Store) ClearMessages(ctx context.Context, conversationID int64) error {
|
|
_, err := s.db.ExecContext(ctx, `DELETE FROM chat_messages WHERE conversation_id = ?`, conversationID)
|
|
return err
|
|
}
|