fix(channelbridge): IM 渠道也走「回合必落可见回复」(与网关同口径)
根因(agent-194,文件:行): - inbound.go 的 deliverReply 对空回复直接 return(静默)⇒ 只剩 user 消息; - runInboundTurn 报错直接 return ⇒ 失败回合连说明都没有。 修法:抽共享**纯函数**包 internal/runtime/turnreply(从网关逐字搬运、零语义改动)+ channelbridge/turnreply.go 的 turnVisibleReply(与网关 persistTurnReply 同构); 取消边界在 IM 用 context.Canceled / ctx 取消表达(渠道桥无代次概念,如实登记差异)。 测试 6 条:空回复/纯空白/轮次用尽/安全网/回合报错/取消不落库/正常逐字不变。 变异:还原旧静默行为 ⇒ 4 条红(含「出站 0 条,want 1」与英文内部诊断外泄)。
This commit is contained in:
1 parent
be38651ba4
commit
fbbbb4ea64
6 files changed
+380
-73
No files matched your search
@@ -0,0 +1,52 @@
|
||||
// Package turnreply 统一「一个回合应当交付给用户看的可见回复文本」的口径。
|
||||
//
|
||||
// 两条编排路径都受同一条不静默铁律约束 —— **归本代次、且不是被用户打断的
|
||||
// 回合,用户一定要看到一条回复**:网关(Web / REST / WS 回合,见
|
||||
// internal/services/gateway/session_turn_reply.go)与渠道桥(IM 回合,见
|
||||
// internal/services/channelbridge/turnreply.go)。没有真实文本时补的是同一份
|
||||
// 中文诚实说明;把它放在共享包里,是为了让文案只有一处定义 —— 两条路径各写
|
||||
// 一套「抱歉我出问题了」迟早会漂移成两种说法,而它们是同一张脸在说话。
|
||||
//
|
||||
// 本包只做纯映射:输入 *loop.Result,输出该交付的文本。**是否该落库**(被取消、
|
||||
// 陈旧代次、静默内部流程……)由调用方按各自的编排状态判定,不在本包内 ——
|
||||
// 网关有会话代次,IM 没有,这个差异必须留在各自的编排器里。
|
||||
package turnreply
|
||||
|
||||
import (
|
||||
"strings"
|
||||
|
||||
"git.yeij.top/AskaEth/Cyrene_v2/internal/runtime/loop"
|
||||
)
|
||||
|
||||
// 静默收尾的诚实说明文案(全部中文,按结束原因区分)。它们是**用户可见**的聊天
|
||||
// 内容,因此只说明「没答上来 + 下一步能怎么办」,不写内部术语、不写堆栈。
|
||||
const (
|
||||
// FallbackEmptyReply 用于模型给出空回复的回合(没有正文、也没有工具调用)。
|
||||
FallbackEmptyReply = "抱歉,我这次没能组织出回复内容(模型返回了空回复)。你可以再说一次,或者换个说法。"
|
||||
// FallbackMaxRounds 用于工具循环耗尽轮次预算仍没得出结论的回合。
|
||||
FallbackMaxRounds = "抱歉,我这次的工具调用反复失败、把思考轮次用尽了,还没能得出结论。你可以再说一次,或者把要求拆小一点。"
|
||||
// FallbackToolLoop 用于关键工具循环安全网终止的回合(同一个工具调用跨轮重复)。
|
||||
FallbackToolLoop = "抱歉,我在同一个工具调用上反复碰壁,已经把这次回合停下了。你可以换个说法再说一次。"
|
||||
// FallbackError 用于回合因内部错误(模型 / 工具 / 编排)中断的回合。
|
||||
FallbackError = "抱歉,我这边出了点问题,这个回合没能给出回复。你可以稍后再试一次。"
|
||||
)
|
||||
|
||||
// Text 返回本回合**应当交付**的可见回复文本:真实文本逐字原样返回,
|
||||
// 没有可见文本、或只有关键工具循环安全网塞进来的内部英文文案时,换成按结束
|
||||
// 原因区分的诚实说明。res 为 nil(回合报错、没带回结果)按内部错误处理。
|
||||
func Text(res *loop.Result) string {
|
||||
if res == nil {
|
||||
return FallbackError
|
||||
}
|
||||
if strings.TrimSpace(res.Text) != "" && res.StopReason != loop.StopReasonToolLoopTerminated {
|
||||
return res.Text
|
||||
}
|
||||
switch res.StopReason {
|
||||
case loop.StopReasonToolLoopTerminated:
|
||||
return FallbackToolLoop
|
||||
case loop.StopReasonMaxRounds:
|
||||
return FallbackMaxRounds
|
||||
default:
|
||||
return FallbackEmptyReply
|
||||
}
|
||||
}
|
||||
Reference in new issue
Block a user