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

- 只翻注释/文档字符串:`go/scanner` 剥注释后按 token 序列+literal 逐 token 比对,**54/54 文件 SAME**;
  改动文件总行数与 HEAD 漂移 = 0(严格 1:1,无合并/拆行)
- 裁决编号与 design 节号逐字保留(03.4.1/03.4.2/03.4.3/14.4.1/14.4.5/07.4.2-4、design/04 §3.1/§3.2 等);
  `chat_template_kwargs` / `enable_thinking` / `reasoning_effort` / `thinking:{type}` 字段名与形状说明未动
- 存疑译法(已登记):`persona` 在叙事语境用「角色」、标识符语境保留 `persona`(仓库既有模块本身混用);
  `rung`→「级」;`provider` 存在「提供商/提供者」两种落笔(可按需一键统一)
- 复核:build/vet 绿 + 两包测试绿;gofmt 干净;残留英文注释 0 条
- 既有存量(未修,只报告):`model/anthropic_test.go` 612 行 >500;`applyAnthropicEvent` 115 行 >80
This commit is contained in:
AskaEth committed 2026-10-04 16:27:54 +08:00
1 parent f5cf117482
commit 3dc1232bc2
54 files changed
+1923 -1923

No files matched your search

+56 -56
View File
@@ -15,58 +15,58 @@ import (
"git.yeij.top/AskaEth/Cyrene_v2/internal/logger"
)
// The push outlet (D1, design/12 §4/§6): proactive messages are mirrored to an
// external push service so the owner's mobile client is reached even when no
// WebSocket client or IM channel is live. Delivery is two-tier by design:
// 推送出口(D1,design/12 §4/§6):主动消息被镜像到
// 外部推送服务,使主人的移动端即便在没有
// WebSocket 客户端或 IM 渠道在线时也能被触达。按设计投递分两级:
//
// 1. the owner's self-hosted unified push service (primary; PUSH_EXPORTER_URL),
// 2. Getui (个推) as the fallback for when the self-hosted service is down.
// 1. 主人的自托管统一推送服务(主级;PUSH_EXPORTER_URL),
// 2. 个推(Getui)作为自托管服务不可用时的降级。
//
// Tier 2 has no SDK integration yet, so an unavailable primary logs an explicit
// "Getui fallback not integrated" note and reports not-delivered instead of
// pretending the message went out. The hook is fire-and-forget: it never delays
// or breaks the existing active-client / IM delivery.
// 第 2 级尚未接入 SDK,因此主级不可用时只记一条明确的
// "Getui fallback not integrated" 备注,并上报未投递,而不
// 假装消息已发出。该钩子是发后不管:它绝不延迟
// 或破坏既有的活跃客户端 / IM 投递。
// defaultExportTimeout bounds one export attempt so a hung endpoint cannot pin a
// goroutine forever.
// defaultExportTimeout 约束单次导出尝试,因此挂死的端点无法永久
// 占住一个 goroutine。
const defaultExportTimeout = 5 * time.Second
// maxExportResponseBytes caps how much of the outlet's response body is drained
// before the connection is reused, so a hostile/buggy endpoint cannot stream an
// unbounded body into memory.
// maxExportResponseBytes 限制连接复用前从出口响应体里
// 抽掉多少数据,因此恶意或有缺陷的端点无法把一个
// 无界的响应体流进内存。
const maxExportResponseBytes = 4 << 10
// PushExporter reports one proactive message to an external push outlet. Export
// must be safe for concurrent use and must honor ctx. A nil error with
// delivered=false means the outlet could not deliver (for example the fallback
// tier is not wired); the caller treats that as a logged miss, never a failure
// of the local push path.
// PushExporter 把一条主动消息上报给外部推送出口。Export
// 必须并发安全且必须尊重 ctx。nil 错误配上
// delivered=false 表示出口无法投递(例如降级
// 级尚未接线);调用方把它当作一次记账的未命中,绝不当作本地
// 推送路径的失败。
type PushExporter interface {
Export(ctx context.Context, msg adapter.UnifiedMessage) (delivered bool, err error)
}
// PushOutletConfig carries the push-outlet wiring. Enabled=false disables the
// hook entirely (NewPushOutlet returns nil). URL/Token/Timeout describe the
// self-hosted primary service; the Getui* fields are reserved for the deferred
// fallback and are not consumed yet.
// PushOutletConfig 携带推送出口的接线。Enabled=false 完全关闭
// 该钩子(NewPushOutlet 返回 nil)。URL/Token/Timeout 描述
// 自托管主服务;Getui* 字段保留给延后的
// 降级级,目前尚未消费。
type PushOutletConfig struct {
// Enabled turns the outlet hook on.
// Enabled 打开出口钩子。
Enabled bool
// URL is the self-hosted unified push service endpoint (HTTP POST JSON).
// Empty leaves the primary tier unconfigured.
// URL 是自托管统一推送服务端点(HTTP POST JSON)。
// 为空则主级保持未配置。
URL string
// Token is sent as "Authorization: Bearer <token>". It is never logged.
// Token 以 "Authorization: Bearer <token>" 发送。它绝不写日志。
Token string
// Timeout bounds one export attempt. Zero uses defaultExportTimeout.
// Timeout 约束单次导出尝试。为零用 defaultExportTimeout。
Timeout time.Duration
// Log is the base logger. Nil uses a discard logger.
// Log 是基础日志器。nil 则用丢弃式日志器。
Log *slog.Logger
}
// NewPushOutlet builds the two-tier push outlet from cfg. It returns nil when
// the hook is disabled, so the pusher simply skips the export step. When it is
// enabled the primary tier is the self-hosted HTTP endpoint (present only when
// URL is set) and the fallback tier is Getui, which is not integrated yet.
// NewPushOutlet 由 cfg 构建两级推送出口。钩子关闭时它返回 nil,
// 因此推送器直接跳过导出步骤。启用时,
// 主级是自托管 HTTP 端点(仅当
// URL 已设置时存在),降级级是个推,尚未接入。
func NewPushOutlet(cfg PushOutletConfig) PushExporter {
if !cfg.Enabled {
return nil
@@ -90,19 +90,19 @@ func NewPushOutlet(cfg PushOutletConfig) PushExporter {
return &pushOutlet{primary: primary, log: log}
}
// pushOutlet is the two-tier exporter: self-hosted service first, Getui second.
// The fallback is nil until the Getui SDK is integrated, so a primary miss is
// logged and reported as not delivered rather than silently dropped.
// pushOutlet 是两级导出器:先自托管服务,再个推。
// 在个推 SDK 接入前降级级为 nil,因此主级未命中时
// 只记日志并上报未投递,而不是静默丢弃。
type pushOutlet struct {
primary PushExporter
fallback PushExporter
log *slog.Logger
}
// Export implements PushExporter. It tries the primary tier and, when that does
// not deliver, the fallback tier. With no fallback wired it logs the pending
// integration and returns (false, nil): the caller treats that as a miss, never
// as a reason to fail the proactive push.
// Export 实现 PushExporter。它先试主级,主级
// 未投递时再试降级级。未接降级级时它记录待
// 接入状态并返回 (false, nil):调用方把这当作未命中,
// 绝不当作让主动推送失败的理由。
func (o *pushOutlet) Export(ctx context.Context, msg adapter.UnifiedMessage) (bool, error) {
if o.primary != nil {
delivered, err := o.primary.Export(ctx, msg)
@@ -123,34 +123,34 @@ func (o *pushOutlet) Export(ctx context.Context, msg adapter.UnifiedMessage) (bo
return false, nil
}
// pushExportPayload is the JSON body POSTed to the self-hosted push service. It
// is deliberately small and stable: the service owns device targeting, the
// message carries only what is needed to render and de-duplicate it.
// pushExportPayload 是 POST 到自托管推送服务的 JSON 体。它
// 刻意小而稳定:设备寻址归该服务,消息
// 只携带渲染与去重所需的内容。
type pushExportPayload struct {
// Source identifies the producer so the service can route/filter.
// Source 标识生产者,好让服务能路由/过滤。
Source string `json:"source"`
// Title is a short display title (the persona name).
// Title 是简短显示标题(角色名)。
Title string `json:"title"`
// Content is the proactive message body (already stripped of internal
// decision markers by buildProactiveMessage).
// Content 是主动消息正文(内部决策标记
// 已由 buildProactiveMessage 剥掉)。
Content string `json:"content"`
// Platform is the outbound platform tag (cyrene-backthink or a concrete IM
// platform).
// Platform 是出站平台标签(cyrene-backthink 或具体的 IM
// 平台)。
Platform string `json:"platform"`
// Timestamp is the message time in Unix milliseconds.
// Timestamp 是消息时间,Unix 毫秒。
Timestamp int64 `json:"timestamp"`
}
// httpPushExporter posts the message to the self-hosted push service. A 2xx
// response means delivered; any other status or transport error is an error.
// The token travels only in the Authorization header and never reaches a log.
// httpPushExporter 把消息 POST 到自托管推送服务。2xx
// 响应表示已投递;其它任何状态或传输错误都算错误。
// token 只出现在 Authorization 头里,绝不进入日志。
type httpPushExporter struct {
url string
token string
client *http.Client
}
// Export implements PushExporter over HTTP POST JSON.
// Export 实现 PushExporter,走 HTTP POST JSON。
func (e *httpPushExporter) Export(ctx context.Context, msg adapter.UnifiedMessage) (bool, error) {
body, err := json.Marshal(pushExportPayload{
Source: "cyrene/backthink",
@@ -182,8 +182,8 @@ func (e *httpPushExporter) Export(ctx context.Context, msg adapter.UnifiedMessag
return true, nil
}
// redact removes the endpoint URL from a transport error so a secret embedded in
// the URL (for example a query token) never reaches a log line.
// redact 从传输错误里移除端点 URL,因此 URL 中内嵌的
// 秘密(例如查询参数里的 token)绝不进入日志行。
func (e *httpPushExporter) redact(err error) error {
if err == nil || e.url == "" {
return err