feat(backthink): 思考轮工具面补齐(裁决 15)—— 能力面接入 + 只读 capability_list + 本轮状态快照
- 缺口 d:状态在**思考前**读一次,同一份快照既喂思考轮又喂 Decide(读不到 = Known=false,绝不伪装成中性状态) - 缺口 c:新增只读工具 capability_list(owner-only、三重输出边界、读写隔离),她可自查当下真实可用面 - 缺口 b:内置允许集补 transcode / capability_list(此前 CAPACITY_ENABLED=true 时新工具会从模型可见面消失) - 缺口 e:guidancePrompt 旧文案承诺的「IoT/日历/提醒」在全仓根本没有对应工具(chat 侧也没有)⇒ 按诚实化改为「与主人对话同等工具面 + 指名自查入口」,不再有空头支票 - (a) 未做且**不自创**:那三把工具无任何设计规格(名字/schema/读写边界/输出上限)⇒ 已报回并登记进 design/20(裁决:走能力/插件/MCP 暴露路线) - 变异实测:允许集去掉新工具 ⇒ TestDecide_AllowedSets + 组合根跨层测试红;丢掉状态快照 ⇒ TestLoopThinker_Think_InjectsRoundStateBlock 红 - 已知弱项(如实登记):组合根那行 wireCapabilitySurface() 调用本身无测试覆盖(与既有 wireTranscode 同惯例)
This commit is contained in:
1 parent
34cef95e17
commit
321cc3b763
14 files changed
+1664
-73
No files matched your search
@@ -6,9 +6,11 @@ import (
|
||||
"log/slog"
|
||||
"strconv"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
"git.yeij.top/AskaEth/Cyrene_v2/internal/iot"
|
||||
"git.yeij.top/AskaEth/Cyrene_v2/internal/logger"
|
||||
"git.yeij.top/AskaEth/Cyrene_v2/internal/runtime/history"
|
||||
)
|
||||
|
||||
// StateProvider 为打扰决策提供用户当前状况
|
||||
@@ -71,6 +73,44 @@ func (p *IoTStateProvider) Current(ctx context.Context) (UserState, error) {
|
||||
return state, nil
|
||||
}
|
||||
|
||||
// currentState 读取用户当前状况,并回答「到底读到了没」:打扰决策用它作为中性
|
||||
// 回退(已知为 false 时按零值判定),思考轮用它决定要不要注入状态块(X1 缺口 d
|
||||
// 让同一份快照同时服务两侧)。提供者为 nil 或读取失败都返回 Known=false,并记一条
|
||||
// 带来源的 warn 日志 —— 绝不把「读不到」伪装成一份中性状态去误导她的判断。
|
||||
func (b *Backthink) currentState(ctx context.Context) (UserState, bool) {
|
||||
if b.deps.State == nil {
|
||||
return UserState{}, false
|
||||
}
|
||||
s, err := b.deps.State.Current(ctx)
|
||||
if err != nil {
|
||||
b.log.Warn("backthink state provider failed", "error", err)
|
||||
return UserState{}, false
|
||||
}
|
||||
return s, true
|
||||
}
|
||||
|
||||
// lastUserActivity 报告主人最近一条消息的墙钟时间
|
||||
// (在主会话里),以及是否找到了任何用户消息。它是活动
|
||||
// 门的活动信号(design/12 §6):提供者为 nil、读取失败或
|
||||
// 尾部为空都得到 has=false,因此活动门会落到当前
|
||||
// 行为而不是靠猜。最近的一条用户消息是最近尾部里
|
||||
// 最新的 RoleUser 条目(Recent 返回的是最旧在前)。
|
||||
func (b *Backthink) lastUserActivity(ctx context.Context) (time.Time, bool) {
|
||||
if b.deps.Recent == nil {
|
||||
return time.Time{}, false
|
||||
}
|
||||
msgs, err := b.deps.Recent.Recent(ctx, history.MainSessionID, recentContextCount)
|
||||
if err != nil {
|
||||
return time.Time{}, false
|
||||
}
|
||||
for i := len(msgs) - 1; i >= 0; i-- {
|
||||
if msgs[i].Role == history.RoleUser {
|
||||
return time.UnixMilli(msgs[i].CreatedAt), true
|
||||
}
|
||||
}
|
||||
return time.Time{}, false
|
||||
}
|
||||
|
||||
// numState 从设备状态 map 中按 keys 读取首个数值。
|
||||
func numState(d iot.Device, keys ...string) (int, bool) {
|
||||
for _, k := range keys {
|
||||
|
||||
Reference in new issue
Block a user