Files
Cyrene_v2/internal/services/backthink/thinker.go
T
AskaEth 3dc1232bc2
CI / Backend (build / vet / test / cross-compile) (push) Has been cancelled
CI / Frontend (tsc + vite build) (push) Has been cancelled
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
2026-10-04 16:27:54 +08:00

48 lines
1.8 KiB
Go

package backthink
import (
"context"
"fmt"
"git.yeij.top/AskaEth/Cyrene_v2/internal/runtime/loop"
)
// LoopThinker 把 *loop.Loop 适配为 Thinker。它是生产接线,
// 让一次自主后台轮驱动完整的工具循环(记忆
// 注入、模型步骤、IoT/日历/提醒等工具调用),同时看到
// 主会话的最近对话并在 owner 环境下运行。
type LoopThinker struct {
loop *loop.Loop
recent recentProvider
}
// NewLoopThinker 把 l 包装成基于给定最近消息提供者的 Thinker
// (生产中是 *history.Store;nil 会让思考降级为仅用引导提示词,
// 见 mainContext)。
func NewLoopThinker(l *loop.Loop, recent recentProvider) *LoopThinker {
return &LoopThinker{loop: l, recent: recent}
}
// Think 经被包装的 loop 跑一轮无人值守思考并返回
// 结论文本。它继承主会话的最近对话作为输入
// 上下文,并注入 owner 会话环境(MemWritable=true、ActorOwner、
// 完整工具集),因此该次思考能读写记忆并调用工具。loop 的
// Run 会话 id 是本服务自己的(不是主会话 id),所以该次思考绝不会
// 与活跃主会话的持久化检查点存储冲突(design/20)。
// 未注入 loop 时返回 ErrNoLoop。
func (t *LoopThinker) Think(ctx context.Context, sessionID, trigger string) (string, error) {
if t.loop == nil {
return "", ErrNoLoop
}
recent := mainContext(ctx, t.recent)
messages := thinkInput(recent, trigger)
envCtx := loop.WithSessionEnv(ctx, loop.OwnerEnv())
// 静音 UI 广播:后台反思不得把其中间
// 推理泄漏进面向用户的 chat 流(它只需要结论)。
res, err := t.loop.Run(loop.WithMutedBroadcast(envCtx), sessionID, messages)
if err != nil {
return "", fmt.Errorf("backthink: think: %w", err)
}
return res.Text, nil
}