feat(channel): owner 车道结构化参与闸与可调旋钮(乙 = C)
主人 2026-10-13 裁决「乙 C」= 默认按甲(群里不对她说就不开口)+ 可调旋钮。 - inbound.go: owner 不再无条件短路参与闸(去掉 `!actor.IsOwner()` 门), 主人群消息改走 shouldRespond 的 owner 车道分支;主人私聊恒回。 - ownerlane.go(新): owner 车道结构化闸 + 判据 `msg.AddressedToMe || (msg.SelfID == "" && len(msg.Mentions) > 0)` (未接线渠道退回旧判据,保护 kook/webhook 的群 @);指向她本人必回(硬保留); 非指向消息按每群旋钮——默认只进上下文不回(registerSilenced 落隔离会话)。 「少说点」类关键词落成结构化降频配置,带 source 日志。 - channelbridge.go: Options.OwnerLaneFor/OwnerLaneSet 读写接缝 + Bridge 状态。 - engage.go: 冷避词表并入「少说点」(与既有「少说两句」同义)。 - runtimeconfig/channels_ownerlane.go(新): owner_lane.json 落盘面 (默认档 + 每群覆盖,可读可改,面板可写)。 - wire_channels.go: 注入 owner_lane.json 存储($DATA_DIR/config/)。 - 测试:不对她说就不回(进上下文零回复)/ @她必回(即使降频)/ 未接线退回 旧判据 / 降频生效且可恢复 + 频率闸 / 旋钮读写接缝 / 归属不变量闭合 / 陌生人私聊与主人私聊回归。变异自证:恢复 owner 短路 ⇒ 5 条用例红。
This commit is contained in:
1 parent
3f266c26b2
commit
537a8b7988
11 files changed
+917
-21
No files matched your search
@@ -108,6 +108,12 @@ func (a *app) wireChannels() error {
|
||||
// 入站附件的目录口径与文档摄取层(wire_runtime.go 的 docResolver)同源,
|
||||
// 两处必须指向同一棵目录树,否则附件会落在一个地方、抽取去另一个地方找。
|
||||
docDataDir := resolveDataDir(a.cfg)
|
||||
// owner 车道结构化旋钮(design/18 §11「乙 = C」)的落盘面:主人在群里说「少说点」
|
||||
// 这类诉求被写成 $DATA_DIR/config/owner_lane.json(可读可改,面板后续照此写入)。
|
||||
// 它只承载「说不说 / 多频繁」,不承载任何身份/权限信息。
|
||||
ownerLane := runtimeconfig.NewOwnerLaneStore(
|
||||
runtimeconfig.DefaultOwnerLanePath(docDataDir),
|
||||
logger.WithSource(a.log, "services/channelbridge/ownerlane"))
|
||||
bridge, berr := channelbridge.New(channelbridge.Options{
|
||||
Log: logger.WithSource(a.log, "services/channelbridge"),
|
||||
Loop: a.loop,
|
||||
@@ -145,6 +151,23 @@ func (a *app) wireChannels() error {
|
||||
PersonaPrompt: a.defaultInstructions(),
|
||||
Engage: channelbridge.DefaultEngageConfig(),
|
||||
// EngageFor 留空(P2a);按群覆盖随 P2c 到来。
|
||||
// OwnerLaneFor / OwnerLaneSet 是 owner 车道结构化旋钮(design/18 §11「乙 = C」)
|
||||
// 的读取/落盘接缝:读接口按 (platform, groupID) 返回该群生效策略(缺省 = 不对她说
|
||||
// 就不开口),写接口把「少说点」这类结构化诉求落进 owner_lane.json,也是面板后续
|
||||
// 写入的那一份。它只影响说不说/多频繁,绝不触碰权限与 actor 元数据。
|
||||
OwnerLaneFor: func(platform, groupID string) *channelbridge.OwnerLanePolicy {
|
||||
p := ownerLane.PolicyFor(platform, groupID)
|
||||
return &channelbridge.OwnerLanePolicy{
|
||||
ReplyToUnaddressed: p.ReplyToUnaddressed,
|
||||
MinReplyGapSec: p.MinReplyGapSec,
|
||||
}
|
||||
},
|
||||
OwnerLaneSet: func(platform, groupID string, p channelbridge.OwnerLanePolicy) error {
|
||||
return ownerLane.Set(platform, groupID, runtimeconfig.OwnerLanePolicy{
|
||||
ReplyToUnaddressed: p.ReplyToUnaddressed,
|
||||
MinReplyGapSec: p.MinReplyGapSec,
|
||||
})
|
||||
},
|
||||
// Factory 让面板保存时热替换某平台的适配器而无需重启(design/04 §3.1)。
|
||||
Factory: factory,
|
||||
// Channels 让热重载把新适配器写回能力注册表:管理面板(渠道卡片、账号在线
|
||||
|
||||
Reference in new issue
Block a user