docs(comments): 注释中文化 · internal/runtime/model + internal/services/backthink(54 文件,纯替换)
- 只翻注释/文档字符串:`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:
1 parent
f5cf117482
commit
3dc1232bc2
54 files changed
+1923
-1923
No files matched your search
@@ -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
|
||||
|
||||
Reference in new issue
Block a user