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
@@ -6,63 +6,63 @@ import (
|
||||
"unicode"
|
||||
)
|
||||
|
||||
// The autonomous think is guided (guidancePrompt in context.go) to conclude with
|
||||
// a compact, machine-parseable decision so the service no longer has to infer
|
||||
// whether to push from the trigger's importance alone (design/20 §2 P2):
|
||||
// 自主思考被引导(context.go 的 guidancePrompt)以如下紧凑、
|
||||
// 机器可解析的决策收尾,好让服务不必再从触发的重要度
|
||||
// 单独推断是否推送(design/20 §2 P2):
|
||||
//
|
||||
// [我决定:push] (or no_push)
|
||||
// [我决定:push] (或 no_push)
|
||||
// [渠道:web|im|kook|telegram|...|auto]
|
||||
// <the warm message body>
|
||||
// <温暖的正文内容>
|
||||
//
|
||||
// The markers are parsed as plain text so a model that formats them slightly
|
||||
// differently still yields a usable decision; a malformed/ambiguous decision
|
||||
// marker fails safe to "no push".
|
||||
// 这些标记按纯文本解析,因此模型稍有不同地
|
||||
// 格式化它们时仍能得出可用的决策;格式错乱/含糊的决策
|
||||
// 标记失败安全为「不推送」。
|
||||
var (
|
||||
// decideMarker matches the push/no_push decision token, tolerating a colon in
|
||||
// either width and optional spaces. It is used to recover the decision, so it
|
||||
// stays strict on the bracketed form: a bare "我决定:push" is treated as prose,
|
||||
// not as a decision (fail safe).
|
||||
// decideMarker 匹配 push/no_push 决策词,容忍两种宽度的
|
||||
// 冒号与可选空格。它用于恢复决策,所以对
|
||||
// 带括号的形式保持严格:裸的 "我决定:push" 被当作散文,
|
||||
// 而不是决策(失败安全)。
|
||||
decideMarker = regexp.MustCompile(`(?i)\[\s*我决定\s*[::]\s*(no_push|push)\s*\]`)
|
||||
// channelMarker matches the target-channel token on the decision line.
|
||||
// channelMarker 匹配决策行上的目标渠道词。
|
||||
channelMarker = regexp.MustCompile(`(?i)\[\s*渠道\s*[::]\s*([a-z0-9_\-]+)\s*\]`)
|
||||
// decidePrefixes are the marker shapes that signal a decision was attempted
|
||||
// but could not be parsed, so the pass is treated as ambiguous (fail safe). It
|
||||
// is deliberately the bracketed form only, so a message that merely contains
|
||||
// "我决定:" in prose (common in Chinese) is not misread as a malformed marker.
|
||||
// decidePrefixes 是「尝试了决策但无法解析」的标记形状,
|
||||
// 这类轮次被视为含糊(失败安全)。它
|
||||
// 刻意只含带括号形式,因此仅仅在散文中出现
|
||||
// "我决定:"(中文里很常见)的消息不会被误读为格式错乱的标记。
|
||||
decidePrefixes = []string{"[我决定"}
|
||||
|
||||
// stripDecideRe / stripChannelRe recognize the decision/channel markers as a
|
||||
// token to delete from the user-facing body, in their intended bracketed form
|
||||
// and with full-width brackets, so a well-formatted decision never leaks.
|
||||
// stripDecideRe / stripChannelRe 把决策/渠道标记识别为
|
||||
// 需要从用户可见正文中删除的词,按它们预期的带括号形式
|
||||
// 与全角括号形式处理,因此格式良好的决策永不泄漏。
|
||||
stripDecideRe = regexp.MustCompile(`(?i)[【\[]\s*我决定\s*[::]\s*(no_push|push)\s*[】\]]`)
|
||||
stripChannelRe = regexp.MustCompile(`(?i)[【\[]\s*渠道\s*[::]\s*[a-z0-9_\-]+\s*[】\]]`)
|
||||
bareDecideRe = regexp.MustCompile(`(?i)我决定\s*[::]\s*(no_push|push)`)
|
||||
bareChannelRe = regexp.MustCompile(`(?i)渠道\s*[::]\s*[a-z0-9_\-]+`)
|
||||
)
|
||||
|
||||
// nonePhrases are conclusions that mean "nothing to report" when no marker is
|
||||
// present. The body is normalized (case-folded, punctuation/spaces stripped)
|
||||
// before comparison so "无", "无。" and "Nothing to report." all collapse to the
|
||||
// same token.
|
||||
// nonePhrases 是没有标记时表示「无可汇报」的结论。
|
||||
// 正文在比较前先归一化(折叠大小写、去掉标点/空格),
|
||||
// 因此 "无"、"无。" 与 "Nothing to report." 都收敛到
|
||||
// 同一个词。
|
||||
var nonePhrases = []string{
|
||||
"无", "没什么", "没有", "无物可报", "暂无", "没有值得说的",
|
||||
"nothing", "none", "nothingtoreport", "nothingworthreporting", "nothingnew",
|
||||
}
|
||||
|
||||
// parseProactive recovers the push decision, the target-channel hint and the
|
||||
// clean message body from a think conclusion. It is a pure function: it reads no
|
||||
// state and performs no I/O, so it is safe to call concurrently and cheap to test.
|
||||
// parseProactive 从思考结论中恢复推送决策、目标渠道提示与
|
||||
// 干净的正文消息。它是纯函数:不读状态、不做 I/O,
|
||||
// 因此可安全并发调用、测试成本低。
|
||||
//
|
||||
// Semantics (design/20 §2 P2):
|
||||
// - A well-formed [我决定:push|no_push] marker is authoritative.
|
||||
// - A malformed/ambiguous decision marker → no push (fail safe).
|
||||
// - No marker: a body that reads as "无"/"nothing to report" → no push;
|
||||
// otherwise the body is treated as a proactive message (push=true), matching
|
||||
// the pre-P2 default.
|
||||
// - The channel hint is the [渠道:...] token, lowercased; empty/auto keeps the
|
||||
// default active-client-first, IM-fallback route.
|
||||
// - A push decision whose body is empty or still reads as "nothing" → no push
|
||||
// (fail safe), so a lone marker never pushes an empty message.
|
||||
// 语义(design/20 §2 P2):
|
||||
// - 格式良好的 [我决定:push|no_push] 标记具有权威性。
|
||||
// - 格式错乱/含糊的决策标记 → 不推送(失败安全)。
|
||||
// - 无标记:正文读作 "无"/"nothing to report" → 不推送;
|
||||
// 否则正文被当作主动消息(push=true),与
|
||||
// P2 之前的默认一致。
|
||||
// - 渠道提示是 [渠道:...] 词,转小写;为空/auto 则保持
|
||||
// 默认的活跃客户端优先、IM 降级路由。
|
||||
// - 决策为推送但正文为空或仍读作「无」 → 不推送
|
||||
// (失败安全),因此单独一个标记绝不会推出空消息。
|
||||
func parseProactive(conclusion string) (message, channelHint string, push bool) {
|
||||
text := strings.TrimSpace(conclusion)
|
||||
|
||||
@@ -83,8 +83,8 @@ func parseProactive(conclusion string) (message, channelHint string, push bool)
|
||||
return message, channelHint, push
|
||||
}
|
||||
|
||||
// matchDecide returns the matched decision token (lowercased) and whether a
|
||||
// well-formed decision marker was present.
|
||||
// matchDecide 返回匹配到的决策词(已转小写)以及
|
||||
// 是否存在格式良好的决策标记。
|
||||
func matchDecide(text string) (string, bool) {
|
||||
m := decideMarker.FindStringSubmatch(text)
|
||||
if m == nil {
|
||||
@@ -93,8 +93,8 @@ func matchDecide(text string) (string, bool) {
|
||||
return strings.ToLower(m[1]), true
|
||||
}
|
||||
|
||||
// hasAmbiguousDecide reports whether a decision marker was attempted but could
|
||||
// not be parsed, which the caller treats as "do not push" (fail safe).
|
||||
// hasAmbiguousDecide 报告是否尝试了决策标记但
|
||||
// 无法解析,调用方把它当作「不推送」(失败安全)。
|
||||
func hasAmbiguousDecide(text string) bool {
|
||||
if decideMarker.MatchString(text) {
|
||||
return false
|
||||
@@ -107,9 +107,9 @@ func hasAmbiguousDecide(text string) bool {
|
||||
return false
|
||||
}
|
||||
|
||||
// matchChannel returns the lowercased target-channel token, or "" when the
|
||||
// conclusion carries no (or a malformed) channel marker. A malformed channel
|
||||
// marker degrades to the default route rather than failing the whole pass.
|
||||
// matchChannel 返回已转小写的目标渠道词;结论未携带
|
||||
// (或携带格式错乱的)渠道标记时返回 ""。格式错乱的渠道
|
||||
// 标记降级为默认路由,而不是让整轮失败。
|
||||
func matchChannel(text string) string {
|
||||
m := channelMarker.FindStringSubmatch(text)
|
||||
if m == nil {
|
||||
@@ -118,15 +118,15 @@ func matchChannel(text string) string {
|
||||
return strings.ToLower(m[1])
|
||||
}
|
||||
|
||||
// stripInternalMarkers removes the structured decision/channel markers so a
|
||||
// proactive message body never carries them to the user. It handles the intended
|
||||
// bracketed form ([我决定:push][渠道:kook]) plus the drift forms a model may emit —
|
||||
// bare "我决定:push" / "渠道:kook" (no brackets) and full-width 【我决定:push】 — then
|
||||
// drops any line that becomes empty and collapses the remainder. It is applied
|
||||
// both inside parseProactive (so the message and record are clean) and again as a
|
||||
// final guard in buildProactiveMessage, so a marker cannot survive into the
|
||||
// outbound body no matter how it was formatted. Only our logs/records may carry
|
||||
// the marker; the user-facing message must be pure warm content.
|
||||
// stripInternalMarkers 移除结构化的决策/渠道标记,因此
|
||||
// 主动消息正文绝不会把它们带给用户。它处理预期的
|
||||
// 带括号形式([我决定:push][渠道:kook])以及模型可能发出的漂移形式——
|
||||
// 裸的 "我决定:push" / "渠道:kook"(无括号)与全角 【我决定:push】——然后
|
||||
// 丢弃因此变空的行并压缩剩余部分。它既在
|
||||
// parseProactive 内部应用(使消息与记录干净),又作为
|
||||
// buildProactiveMessage 里的最后一道守护,因此无论标记如何
|
||||
// 被格式化,都无法存活到出站正文里。只有我们的日志/记录可以携带
|
||||
// 该标记;面向用户的消息必须是纯温暖内容。
|
||||
func stripInternalMarkers(text string) string {
|
||||
lines := strings.Split(text, "\n")
|
||||
out := make([]string, 0, len(lines))
|
||||
@@ -144,8 +144,8 @@ func stripInternalMarkers(text string) string {
|
||||
return strings.Join(out, "\n")
|
||||
}
|
||||
|
||||
// looksNone reports whether the body says "nothing worth saying". It is used both
|
||||
// to drive the no-marker default and to fail-safe a contradictory push marker.
|
||||
// looksNone 报告正文是否表示「没什么值得说的」。它既用于
|
||||
// 驱动无标记时的默认,也用于对矛盾的 push 标记失败安全。
|
||||
func looksNone(text string) bool {
|
||||
t := normalizeNone(text)
|
||||
if t == "" {
|
||||
@@ -159,8 +159,8 @@ func looksNone(text string) bool {
|
||||
return false
|
||||
}
|
||||
|
||||
// normalizeNone lowercases the body and strips spaces and punctuation so the
|
||||
// nonePhrases compare cleanly across "无", "无。", "Nothing to report." and similar.
|
||||
// normalizeNone 把正文转小写并去掉空格与标点,好让
|
||||
// nonePhrases 在 "无"、"无。"、"Nothing to report." 之类之间干净比较。
|
||||
func normalizeNone(text string) string {
|
||||
var b strings.Builder
|
||||
for _, r := range strings.ToLower(strings.TrimSpace(text)) {
|
||||
|
||||
Reference in new issue
Block a user