feat(history): 消息搜索/编辑/删除 + 会话置顶(D2/D3/D5)
- history/message_ops.go(新): Search(会话内, q/after互斥, LIKE参数化+%/_转义+大小写不敏感, 严格限定会话doc) / UpdateMessage(返回更新后Message) / DeleteMessage / messageByID / escapeLike
- history/session_pin.go(新): SetPinned; 迁移0009 chat_sessions加pinned INTEGER DEFAULT 0; store.go SessionMeta.Pinned + createSessionsTable加列
- session_preview.go: 查询加s.pinned + ORDER BY pinned DESC,(type=main) DESC,created_at ASC
- gateway history_write.go(新,保持history.go≤500): handlePatchSession(pinned+title) / handlePatchMessage / handleDeleteMessage; server.go加PATCH/DELETE /api/v1/messages/{id} + /sessions/{id}置顶
- history.go: handleListMessages读q分流Search; 契约PATCH title/置顶
- D2会话内搜索(不做跨会话,隔离会话不外泄红线); D3不做重发端点(客户端编辑后再发); D5用pinned bool
- 测试(message_ops/history_messages/migrate_pinned), build/vet/test绿+3平台交叉编译; Docs/api-client v0.30
- 未做: 编辑/删除WS实时广播(message_edited/deleted), 下批
This commit is contained in:
1 parent
c7b2cd8ae0
commit
844b2a74c1
15 files changed
+1091
-73
No files matched your search
@@ -124,9 +124,21 @@ type HistoryStore interface {
|
||||
ListAdapterLog(ctx context.Context, adapterID string, before int64, limit int) ([]history.Message, error)
|
||||
ListAllLog(ctx context.Context, before int64, limit int) ([]history.Message, error)
|
||||
DeleteSession(ctx context.Context, sessionID string) error
|
||||
// Search returns session-scoped content matches (newest first) for the
|
||||
// ?q= message-search path. An empty query yields an empty slice.
|
||||
Search(ctx context.Context, sessionID, query string, before int64, limit int) ([]history.Message, error)
|
||||
// UpdateMessage edits a single message's content and returns the updated
|
||||
// message. An unknown id returns history.ErrMessageNotFound.
|
||||
UpdateMessage(ctx context.Context, id, content string) (history.Message, error)
|
||||
// DeleteMessage removes a single message. An unknown id returns
|
||||
// history.ErrMessageNotFound.
|
||||
DeleteMessage(ctx context.Context, id string) error
|
||||
// RenameSession sets a session's display title (main or sub). An unknown id
|
||||
// returns history.ErrSessionNotFound.
|
||||
RenameSession(ctx context.Context, sessionID, title string) error
|
||||
// SetPinned pins/unpins a session (main or sub). An unknown id returns
|
||||
// history.ErrSessionNotFound.
|
||||
SetPinned(ctx context.Context, sessionID string, pinned bool) error
|
||||
NewSubSession(ctx context.Context, ownerID string) (string, error)
|
||||
ListSessions(ctx context.Context) ([]history.SessionMeta, error)
|
||||
}
|
||||
@@ -471,7 +483,11 @@ func (s *Server) Handler() http.Handler {
|
||||
mux.Handle("GET /api/v1/sessions/{id}/messages", historyAuth(http.HandlerFunc(s.handleListMessages)))
|
||||
mux.Handle("POST /api/v1/sessions", historyAuth(http.HandlerFunc(s.handleCreateSubSession)))
|
||||
mux.Handle("DELETE /api/v1/sessions/{id}", historyAuth(http.HandlerFunc(s.handleDeleteSession)))
|
||||
mux.Handle("PATCH /api/v1/sessions/{id}", historyAuth(http.HandlerFunc(s.handleRenameSession)))
|
||||
mux.Handle("PATCH /api/v1/sessions/{id}", historyAuth(http.HandlerFunc(s.handlePatchSession)))
|
||||
// Single-message edit/delete (Android collaboration batch ③a, D3). A message is
|
||||
// addressed by its own opaque id; both are owner/admin-gated history writes.
|
||||
mux.Handle("PATCH /api/v1/messages/{id}", historyAuth(http.HandlerFunc(s.handlePatchMessage)))
|
||||
mux.Handle("DELETE /api/v1/messages/{id}", historyAuth(http.HandlerFunc(s.handleDeleteMessage)))
|
||||
|
||||
// Realtime.
|
||||
mux.HandleFunc("/ws/chat", s.handleWS)
|
||||
|
||||
Reference in new issue
Block a user