docs(comments): 注释中文化 · internal/runtime/history(15 文件,纯替换)
CI / Backend (build / vet / test / cross-compile) (push) Has been cancelled
CI / Frontend (tsc + vite build) (push) Has been cancelled

- 只翻注释/文档字符串:剥离注释后代码行逐字节不变(机械校验只剩 4 条行尾注释的翻译,代码前缀全等)
- 交叉引用(design/16 §4.6、D4/B3、0010 迁移文件名)逐字保留
- 保留未译技术词:DDL/rowid/LIKE/LEFT JOIN/DTO/rune/WS/actor 及全部标识符与表名
- 顺带副作用:store.go、session_persona_test.go 由注释文字改变而变得 gofmt 干净(未运行 gofmt -w)
This commit is contained in:
AskaEth committed 2026-10-04 12:28:48 +08:00
1 parent b0fbb8bc0d
commit 09fba77f87
15 files changed
+430 -516

No files matched your search

+19 -24
View File
@@ -9,22 +9,20 @@ import (
"time"
)
// This file owns the per-session role binding (DevDocs/design/22 多角色并存 +
// 按会话选角 §2/§4.1). A session's role is the single source of truth for "which
// role answers in this conversation": the loop resolves the system prompt, the
// memory scope, the emotion machine and the thinking budget from it. The value
// is display/scope metadata only — identity and permissions are still decided by
// the channel actor metadata (project red line).
// 本文件负责每会话的角色绑定(DevDocs/design/22 多角色并存 +
// 按会话选角 §2/§4.1)。一个会话的角色是「这个对话里由哪个角色应答」的唯一
// 事实来源:循环据此解析系统提示词、记忆作用域、情绪机与思考预算。该值只是
// 展示/作用域元数据 —— 身份与权限仍由渠道 actor 元数据决定(项目红线)。
//
// '' means "inherit the current global default role", so it is both the column
// default and a legal explicit value: setting it clears an explicit binding and
// lets the session follow a default-role change again (design/22 §7-6).
// 空意味着「继承当前全局默认角色」,因此它既是列默认值,也是一个合法的显式
// 取值:把它设为空即清除显式绑定,让会话重新跟随默认角色变更
// (design/22 §7-6)。
// NewSubSessionFor creates a sub session bound to personaID and returns its id
// (MainSessionID:uuid). A blank personaID binds no explicit role, so the session
// inherits the global default — the same behavior as NewSubSession. ownerID is
// accepted for symmetry with NewSubSession (the Web owner is identified by JWT,
// not stored per session); it is logged at debug and not persisted.
// NewSubSessionFor 创建绑定到 personaID 的子会话并返回其 id
// (MainSessionID:uuid)。personaID 为空则不绑定任何显式角色,会话因此继承
// 全局默认 —— 与 NewSubSession 行为相同。ownerID 为与 NewSubSession 对称而
// 接受(Web 主人由 JWT 识别,不按会话存储);它只以 debug 级别记日志,不被
// 持久化。
func (s *Store) NewSubSessionFor(ctx context.Context, ownerID, personaID string) (string, error) {
id, err := newID()
if err != nil {
@@ -42,11 +40,10 @@ func (s *Store) NewSubSessionFor(ctx context.Context, ownerID, personaID string)
return sessionID, nil
}
// SetSessionPersona binds (or clears, when personaID is blank) a session's role.
// Both the fixed main session and sub sessions may be retargeted: the binding is
// scope metadata, not identity. An unknown id returns ErrSessionNotFound. It
// never touches the conversation: the stored messages keep the role that spoke
// them (design/22 §7-5), and the next turn simply resolves the new role.
// SetSessionPersona 绑定(或在 personaID 为空时清除)一个会话的角色。固定主
// 会话与子会话都可被改绑:该绑定是作用域元数据,不是身份。未知 id 返回
// ErrSessionNotFound。它绝不触碰对话:已存消息保留说出它们的那个角色
// (design/22 §7-5),下一个回合只是解析新角色。
func (s *Store) SetSessionPersona(ctx context.Context, sessionID, personaID string) error {
res, err := s.db.ExecContext(ctx, `UPDATE chat_sessions SET persona_id = ? WHERE id = ?`,
strings.TrimSpace(personaID), sessionID)
@@ -63,11 +60,9 @@ func (s *Store) SetSessionPersona(ctx context.Context, sessionID, personaID stri
return nil
}
// SessionPersona returns the role bound to sessionID, or "" when the session
// inherits the global default. An unknown id returns ErrSessionNotFound so a
// caller can tell "no explicit role" (a real session, empty binding) from "no
// such session"; a caller that only needs the effective role treats both as
// "use the default".
// SessionPersona 返回绑定到 sessionID 的角色,会话继承全局默认时返回空。未知
// id 返回 ErrSessionNotFound,使调用方能区分「没有显式角色」(真实会话、绑定
// 为空)与「没有这个会话」;只需要有效角色的调用方把两者都当作「用默认」。
func (s *Store) SessionPersona(ctx context.Context, sessionID string) (string, error) {
var personaID string
err := s.db.QueryRowContext(ctx, `SELECT persona_id FROM chat_sessions WHERE id = ?`, sessionID).Scan(&personaID)