docs(gateway): gateway 剩余文件注释改中文(逐行 1:1,代码零字节改动)
主人 2026-10-03 拍板「注释一律中文」;gateway 至此整包注释中文化完成(本会话共 3 批: 已推库 16 个文件 + 本批剩余文件)。 校验:机械校验(非注释改动行)= 空;剥注释后代码文本逐行比对全等(不一致文件数 0); 全树 go test ./... 58 包 ok / 0 FAIL;交叉编译绿。
This commit is contained in:
1 parent
91e8d7a029
commit
074ffc4ebf
73 files changed
+2529
-2529
No files matched your search
@@ -13,46 +13,46 @@ import (
|
||||
"git.yeij.top/AskaEth/Cyrene_v2/internal/runtime/history"
|
||||
)
|
||||
|
||||
// historySessionSummary is the wire shape of one persistent session (main or sub) in the
|
||||
// GET /api/v1/sessions response.
|
||||
// historySessionSummary 是 GET /api/v1/sessions 响应中一个持久化会话
|
||||
// (main 或 sub)的线上结构。
|
||||
type historySessionSummary struct {
|
||||
ID string `json:"id"`
|
||||
Type string `json:"type"` // "main" | "sub"
|
||||
Title string `json:"title,omitempty"`
|
||||
CreatedAt int64 `json:"createdAt"`
|
||||
// Pinned floats the session to the top of the list (D5). It is order metadata
|
||||
// only and is always present so a client can render/sort without a second call.
|
||||
// Pinned 把会话浮到列表顶部(D5)。它只是排序元数据,
|
||||
// 且始终存在,使客户端无需第二次调用就能渲染/排序。
|
||||
Pinned bool `json:"pinned"`
|
||||
// LastMessage is a display-only preview of the session's newest message, so the
|
||||
// client can render a conversation row (e.g. the Android session list) without a
|
||||
// per-session request. It is omitted for a session with no messages. Content is
|
||||
// already truncated by the store.
|
||||
// LastMessage 是会话最新消息的纯展示预览,使客户端
|
||||
// 无需逐会话请求就能渲染对话行(例如 Android 会话列表)。
|
||||
// 没有消息的会话会省略它。内容
|
||||
// 已由存储截断。
|
||||
LastMessage *historyLastMessage `json:"lastMessage,omitempty"`
|
||||
// UnreadCount is the number of messages newer than the session's read cursor
|
||||
// (D4), derived in the same list query. It is always returned (0 when nothing
|
||||
// is unread) so a client can render/clear the badge without a second call. The
|
||||
// cursor is session-scoped and single-owner: reading on any one end clears the
|
||||
// badge for every end of the account.
|
||||
// UnreadCount 是比会话读游标(D4)更新的消息数,
|
||||
// 在同一次列表查询中推导。它始终返回(无未读时为 0),
|
||||
// 使客户端无需第二次调用就能渲染/清除角标。该
|
||||
// 游标是会话作用域且单归属:在任一端已读会为
|
||||
// 该账号的每一端清除角标。
|
||||
UnreadCount int `json:"unreadCount"`
|
||||
// PersonaID is the role this session belongs to (design/22 §2/§4.5). It is the
|
||||
// single source of truth for which role answers in the conversation, and the
|
||||
// client uses it to render the role's name/avatar for the active session.
|
||||
// Omitted when empty, and empty means "inherit the global default role", so an
|
||||
// old client that ignores the field keeps showing the default role's visuals.
|
||||
// PersonaID 是该会话所属的角色(design/22 §2/§4.5)。它是
|
||||
// 「对话中由哪个角色应答」的唯一事实来源,客户端
|
||||
// 用它为活动会话渲染角色的名字/头像。
|
||||
// 为空时省略,而空意味着「继承全局默认角色」,因此
|
||||
// 忽略该字段的旧客户端仍展示默认角色的视觉。
|
||||
PersonaID string `json:"personaId,omitempty"`
|
||||
}
|
||||
|
||||
// historyLastMessage is the wire shape of the last-message preview in a session summary.
|
||||
// historyLastMessage 是会话摘要中最后消息预览的线上结构。
|
||||
type historyLastMessage struct {
|
||||
Role string `json:"role"` // "user" | "assistant"
|
||||
Content string `json:"content"`
|
||||
CreatedAt int64 `json:"createdAt"`
|
||||
}
|
||||
|
||||
// historyMessage is the wire shape of one persisted chat message in the
|
||||
// GET /api/v1/sessions/{id}/messages response. Mode is carried so the frontend renders
|
||||
// the bubble without guessing (design/16 §5.1); thinking is stored and returned to the
|
||||
// owner/admin (the messages route is owner/admin-only, so it never reaches a viewer).
|
||||
// historyMessage 是 GET /api/v1/sessions/{id}/messages 响应中一条持久化聊天
|
||||
// 消息的线上结构。Mode 被携带,使前端无需猜测就渲染
|
||||
// 气泡(design/16 §5.1);thinking 会被存储并返回给
|
||||
// owner/admin(消息路由仅 owner/admin,因此绝不触达 viewer)。
|
||||
type historyMessage struct {
|
||||
ID string `json:"id"`
|
||||
SessionID string `json:"sessionId"`
|
||||
@@ -64,25 +64,25 @@ type historyMessage struct {
|
||||
Thinking string `json:"thinking,omitempty"`
|
||||
Platform string `json:"platform,omitempty"`
|
||||
DeviceID string `json:"deviceId,omitempty"`
|
||||
// SenderName is the human-readable sender display name of a third-party
|
||||
// message (group/stranger, design/16 §4.6). It is blank for the owner's
|
||||
// private chat on the main session, so empty means "labeled as the owner".
|
||||
// SenderName 是第三方消息(群聊/陌生人,design/16 §4.6)
|
||||
// 给人看的发送者显示名。对主会话中主人的私聊它为
|
||||
// 空,因此空意味着「标记为主人」。
|
||||
SenderName string `json:"senderName,omitempty"`
|
||||
// AdapterID is the adapter (platform + account) registration name of the IM
|
||||
// source that produced the message (e.g. "kook:3bef..."). It is blank for
|
||||
// Web-originated messages.
|
||||
// AdapterID 是产出该消息的 IM 来源适配器(平台 + 账号)
|
||||
// 注册名(例如 "kook:3bef...")。对 Web 来源的消息
|
||||
// 为空。
|
||||
AdapterID string `json:"adapterId,omitempty"`
|
||||
// PersonaID is the role that SPOKE this message (design/22 §7-5). A session may
|
||||
// switch roles while keeping its context, so the authoring role is stored and
|
||||
// returned per message and the client renders the bubble with that role's
|
||||
// name/avatar. Omitted when empty, and empty means "the global default role" —
|
||||
// the pre-multi-character rows read exactly as before.
|
||||
// PersonaID 是说出这条消息的角色(design/22 §7-5)。一个会话可以
|
||||
// 在保留上下文的同时切换角色,因此作者角色按消息
|
||||
// 存储并返回,客户端用该角色的名字/头像渲染
|
||||
// 气泡。为空时省略,而空意味着「全局默认角色」——
|
||||
// 多角色之前的行读起来与以往完全一致。
|
||||
PersonaID string `json:"personaId,omitempty"`
|
||||
CreatedAt int64 `json:"createdAt"`
|
||||
}
|
||||
|
||||
// handleHistorySessions returns the main session first, then every sub session (oldest
|
||||
// first). It is the chat-history session list for the frontend (design/16 §2.2).
|
||||
// handleHistorySessions 先返回主会话,再返回每个子会话(最旧
|
||||
// 优先)。它是前端的聊天历史会话列表(design/16 §2.2)。
|
||||
func (s *Server) handleHistorySessions(w http.ResponseWriter, r *http.Request) {
|
||||
meta, err := s.history.ListSessions(r.Context())
|
||||
if err != nil {
|
||||
@@ -106,8 +106,8 @@ func (s *Server) handleHistorySessions(w http.ResponseWriter, r *http.Request) {
|
||||
writeJSON(w, http.StatusOK, out)
|
||||
}
|
||||
|
||||
// toHistoryLastMessage maps a stored last-message preview to its wire shape, returning
|
||||
// nil for a session that has no messages (so the field is omitted from the JSON).
|
||||
// toHistoryLastMessage 把已存的最后消息预览映射为其线上结构,
|
||||
// 对没有消息的会话返回 nil(因此该字段从 JSON 中省略)。
|
||||
func toHistoryLastMessage(m *history.MessageSummary) *historyLastMessage {
|
||||
if m == nil {
|
||||
return nil
|
||||
@@ -115,21 +115,21 @@ func toHistoryLastMessage(m *history.MessageSummary) *historyLastMessage {
|
||||
return &historyLastMessage{Role: m.Role, Content: m.Content, CreatedAt: m.CreatedAt}
|
||||
}
|
||||
|
||||
// createSubSessionRequest is the POST /api/v1/sessions body. The body itself is
|
||||
// optional (a client that just wants a plain session sends none), and personaId is
|
||||
// the optional role the new session is bound to (design/22 §4.5). It is the
|
||||
// "seed the new session's role" half of the design's precedence: an explicit role
|
||||
// here becomes the session-level binding (the single source of truth), while
|
||||
// omitting it leaves persona_id = '' so the session inherits the global default.
|
||||
// createSubSessionRequest 是 POST /api/v1/sessions 的请求体。请求体本身
|
||||
// 可选(只想要普通会话的客户端不发送任何内容),personaId 是
|
||||
// 新会话可选绑定的角色(design/22 §4.5)。它是设计的
|
||||
// 优先级中「为新会话播种角色」的那一半:此处显式给出的角色
|
||||
// 成为会话级绑定(唯一事实来源),而省略它则
|
||||
// 保持 persona_id = '',使会话继承全局默认。
|
||||
type createSubSessionRequest struct {
|
||||
PersonaID string `json:"personaId"`
|
||||
}
|
||||
|
||||
// handleCreateSubSession creates a new sub session and returns its sessionId. It is a
|
||||
// user-side write, so it is owner/admin-gated like /api/v1/chat. An optional
|
||||
// {"personaId":"..."} body binds the new session to that role; an unknown id is
|
||||
// rejected with 400 rather than creating a session that would silently answer as
|
||||
// the default role.
|
||||
// handleCreateSubSession 创建一个新的子会话并返回其 sessionId。它是
|
||||
// 用户侧写操作,因此与 /api/v1/chat 一样受 owner/admin 门控。可选的
|
||||
// {"personaId":"..."} 请求体把新会话绑定到该角色;未知 id 会
|
||||
// 以 400 拒绝,而不是创建一个会静默以
|
||||
// 默认角色应答的会话。
|
||||
func (s *Server) handleCreateSubSession(w http.ResponseWriter, r *http.Request) {
|
||||
if s.history == nil {
|
||||
writeError(w, &apperr.AppError{Code: "not_implemented", Message: "会话历史服务未配置(未注入 HistoryStore)", HTTPCode: http.StatusNotImplemented})
|
||||
@@ -165,22 +165,22 @@ func (s *Server) handleCreateSubSession(w http.ResponseWriter, r *http.Request)
|
||||
writeJSON(w, http.StatusCreated, resp)
|
||||
}
|
||||
|
||||
// handleListMessages returns a page of messages for a session with cursor pagination.
|
||||
// It is the hot-paging history endpoint (design/16 §2.2, §5.1). Two mutually exclusive
|
||||
// cursors are supported:
|
||||
// - before (millisecond createdAt): newest-first page of messages strictly older than
|
||||
// before — the default, used to page backwards through history;
|
||||
// - after (millisecond createdAt): oldest-first page of messages strictly newer than
|
||||
// after — forward incremental catch-up, so a client that reconnected can pull
|
||||
// everything it missed from the newest createdAt it already has, without the
|
||||
// one-page limit of a backward walk.
|
||||
// handleListMessages 用游标分页返回某会话的一页消息。
|
||||
// 它是热分页历史端点(design/16 §2.2、§5.1)。支持两个互斥的
|
||||
// 游标:
|
||||
// - before(毫秒 createdAt):返回严格早于 before 的消息,最新优先
|
||||
// —— 默认方向,用于向后翻历史;
|
||||
// - after(毫秒 createdAt):返回严格新于 after 的消息,最旧优先
|
||||
// —— 前向增量追赶,使已重连的客户端能拉取
|
||||
// 从其已有的最新 createdAt 起错过的全部内容,而不受
|
||||
// 向后翻的单页上限限制。
|
||||
//
|
||||
// limit defaults to 50 (clamped to 200) for both directions. platform filters the page
|
||||
// by source platform in either direction. An optional q switches the page to a
|
||||
// session-scoped content search (newest first, still honoring before/limit); q is
|
||||
// mutually exclusive with after, and an empty q is ignored so plain paging is
|
||||
// unchanged. Supplying both before and after (both > 0) answers 400, as does a
|
||||
// non-numeric/negative after or an invalid limit/before.
|
||||
// limit 两个方向都默认 50(上限 200)。platform 在任一方向按
|
||||
// 来源平台过滤该页。可选的 q 把该页切换为
|
||||
// 会话作用域的内容搜索(最新优先,仍遵守 before/limit);q 与
|
||||
// after 互斥,空 q 被忽略,因此普通分页
|
||||
// 不变。同时给出 before 与 after(二者都 > 0)返回 400,
|
||||
// after 非数字/为负或 limit/before 非法时亦然。
|
||||
func (s *Server) handleListMessages(w http.ResponseWriter, r *http.Request) {
|
||||
if s.history == nil {
|
||||
writeError(w, &apperr.AppError{Code: "not_implemented", Message: "会话历史服务未配置(未注入 HistoryStore)", HTTPCode: http.StatusNotImplemented})
|
||||
@@ -248,9 +248,9 @@ func (s *Server) handleListMessages(w http.ResponseWriter, r *http.Request) {
|
||||
writeJSON(w, http.StatusOK, out)
|
||||
}
|
||||
|
||||
// parseAfterCursor reads the non-negative "after" query param (a millisecond createdAt
|
||||
// cursor). An absent/empty param yields (0, true) — no forward bound. A non-numeric or
|
||||
// negative value yields (0, false) so the caller answers 400.
|
||||
// parseAfterCursor 读取非负的 "after" 查询参数(毫秒 createdAt
|
||||
// 游标)。参数缺失/为空得到 (0, true) —— 无前向边界。非数字或
|
||||
// 负值得到 (0, false),使调用方返回 400。
|
||||
func parseAfterCursor(r *http.Request) (int64, bool) {
|
||||
raw := r.URL.Query().Get("after")
|
||||
if raw == "" {
|
||||
@@ -263,10 +263,10 @@ func parseAfterCursor(r *http.Request) (int64, bool) {
|
||||
return v, true
|
||||
}
|
||||
|
||||
// handleChannelPlatformLog returns up to limit messages for an IM platform across its
|
||||
// isolated (group/stranger) sessions, newest first, for the admin adapter log page
|
||||
// (design/16 §4.6 §4). It excludes the fixed main web session, so only the platform's
|
||||
// non-owner message stream is surfaced; the owner-private mirror stays out of this view.
|
||||
// handleChannelPlatformLog 为某个 IM 平台跨其隔离(群聊/陌生人)
|
||||
// 会话返回至多 limit 条消息,最新优先,供管理适配器日志页
|
||||
// (design/16 §4.6 §4)。它排除固定的主 Web 会话,因此只浮现该平台的
|
||||
// 非主人消息流;owner 私有镜像不进入该视图。
|
||||
func (s *Server) handleChannelPlatformLog(w http.ResponseWriter, r *http.Request) {
|
||||
if s.history == nil {
|
||||
writeError(w, &apperr.AppError{Code: "not_implemented", Message: "会话历史服务未配置(未注入 HistoryStore)", HTTPCode: http.StatusNotImplemented})
|
||||
@@ -309,13 +309,13 @@ func (s *Server) handleChannelPlatformLog(w http.ResponseWriter, r *http.Request
|
||||
writeJSON(w, http.StatusOK, out)
|
||||
}
|
||||
|
||||
// handleChannelMessages returns up to limit messages for the admin adapter log page,
|
||||
// newest first, across one of three granularities (design/16 §4.6 §4): a single
|
||||
// adapter config (?adapter=kook:3bef...), a whole platform (?platform=kook), or the
|
||||
// full IM adapter overview (neither, so adapter_id != ''). before/limit reuse the
|
||||
// standard cursor pagination. The owner-private mirror on the main web session is
|
||||
// NOT excluded here because it carries the adapter_id; each granularity filters on
|
||||
// adapter_id / platform directly.
|
||||
// handleChannelMessages 为管理适配器日志页返回至多 limit 条消息,
|
||||
// 最新优先,覆盖三种粒度之一(design/16 §4.6 §4):单个
|
||||
// 适配器配置(?adapter=kook:3bef...)、整个平台(?platform=kook),或
|
||||
// 全部 IM 适配器总览(二者都不给,即 adapter_id != '')。before/limit 复用
|
||||
// 标准游标分页。主 Web 会话上的 owner 私有镜像在此
|
||||
// 不被排除,因为它携带 adapter_id;每种粒度直接按
|
||||
// adapter_id / platform 过滤。
|
||||
func (s *Server) handleChannelMessages(w http.ResponseWriter, r *http.Request) {
|
||||
if s.history == nil {
|
||||
writeError(w, &apperr.AppError{Code: "not_implemented", Message: "会话历史服务未配置(未注入 HistoryStore)", HTTPCode: http.StatusNotImplemented})
|
||||
@@ -387,7 +387,7 @@ func (s *Server) handleDeleteSession(w http.ResponseWriter, r *http.Request) {
|
||||
writeJSON(w, http.StatusOK, map[string]any{"deleted": id})
|
||||
}
|
||||
|
||||
// toHistoryMessage maps a stored history.Message to its wire shape.
|
||||
// toHistoryMessage 把已存的 history.Message 映射为其线上结构。
|
||||
func toHistoryMessage(m history.Message) historyMessage {
|
||||
return historyMessage{
|
||||
ID: m.ID,
|
||||
@@ -407,5 +407,5 @@ func toHistoryMessage(m history.Message) historyMessage {
|
||||
}
|
||||
}
|
||||
|
||||
// historyDefaultLimit is the page size used when the client omits the limit query param.
|
||||
// historyDefaultLimit 是客户端省略 limit 查询参数时使用的页大小。
|
||||
const historyDefaultLimit = 50
|
||||
Reference in new issue
Block a user