Files
Cyrene_v2/internal/runtime/loop/step.go
T
AskaEth 91e8d7a029 docs(runtime): internal/runtime/loop 44 个文件注释改中文(逐行 1:1,代码零字节改动)
主人 2026-10-03 拍板「注释一律中文」;本模块按长期分批协议(一个模块一次派工)执行。
注释行数 1329 → 1329 逐行 1:1(含中文 33 → 1304);行尾注释 5 条一并译。
校验:机械校验(非注释改动行)= 空;独立 Go AST 程序(剥注释复渲)证明 44/44 文件代码全等;
全树 go test ./... 58 包 ok / 0 FAIL;交叉编译绿。
gofmt:capacity_loop_test.go / flow.go 改动前即未格式化,按铁律保留原样未动。
2026-10-03 22:28:21 +08:00

80 lines
2.8 KiB
Go
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
package loop
import (
"context"
"fmt"
"git.yeij.top/AskaEth/Cyrene_v2/internal/runtime/agent"
"git.yeij.top/AskaEth/Cyrene_v2/internal/runtime/model"
"git.yeij.top/AskaEth/Cyrene_v2/internal/runtime/trace"
)
// stepOutcome 是循环对单个模型步的内部视图,由
// agent 的 *agent.StepResult(非流式)或流式路径构建的等价物
// 归一化而来。
type stepOutcome struct {
final bool
text string
toolCalls []agent.ToolCall
stopReason string
// modelStopReason 是 provider 对该模型调用的原始 stop/finish
// 原因(Anthropic max_tokens / end_turn / tool_use),记录在 llm_call
// span 上,使即使该步本身正常结束,截断也可见。
modelStopReason string
// model 是服务该调用的路由模型,在流式路径上可知
//(该路径自行构建请求),在 agent 路径上为空。它
// 记录在 llm_call span 的日志事件上。
model string
}
// step 运行单次模型调用。配置了 OnStream 回调时,它
// 直接驱动适配器的 ChatStream,把增量串给 OnStream 并
// 应用循环的护栏;否则委托给 agent 的 RunStep,
// 由后者运行 agent 自身的护栏并记录自己的 CallRecord。整个
// 调用被包在 llm_call span 中,使 M9 面板能看到每次 LLM 调用。
func (l *Loop) step(ctx context.Context, sessionID string, messages []model.Message) (*stepOutcome, error) {
_, llmSpan := l.span(ctx, "llm.call", trace.SpanKindLLM)
var (
out *stepOutcome
err error
)
// 静音(内部自主流程)绕过流式:它既不流向
// UI,也不付流式路径的额外开销。正常聊天则流式。
if l.onStream != nil && !isMutedBroadcast(ctx) {
out, err = l.streamStep(ctx, messages)
} else {
out, err = l.agentStep(ctx, sessionID, messages)
}
if err != nil {
l.spanProp(llmSpan, "error", err.Error())
l.finishSpan(llmSpan, trace.SpanStatusError)
return nil, fmt.Errorf("loop: model step: %w", err)
}
l.spanProp(llmSpan, "stop_reason", out.stopReason)
if out.modelStopReason != "" {
l.spanProp(llmSpan, "model_stop_reason", out.modelStopReason)
}
l.spanProp(llmSpan, "tool_calls", len(out.toolCalls))
l.recordLLMDone(llmSpan, out, l.agentFor(ctx))
l.finishSpan(llmSpan, trace.SpanStatusOK)
return out, nil
}
// agentStep 把非流式步委托给该 turn 的 agent,由后者运行输入
// 与输出护栏、调用模型并解码所有工具调用。
func (l *Loop) agentStep(ctx context.Context, sessionID string, messages []model.Message) (*stepOutcome, error) {
sr, err := l.agentFor(ctx).RunStep(ctx, sessionID, messages)
if err != nil {
return nil, fmt.Errorf("loop: agent step: %w", err)
}
return &stepOutcome{
final: sr.Final,
text: sr.Text,
toolCalls: sr.ToolCalls,
stopReason: sr.StopReason,
modelStopReason: sr.ModelStopReason,
}, nil
}