mirror of
https://gitcode.com/JianFeeeee/HomeAgent.git
synced 2026-09-21 09:28:14 +00:00
## 现象
生产日志(v1.3.1 启动)出现:
`[plugin] qq 只声明了输出通道 "qq",已按双向通道兜底登记 inputch;若要明确意图请显式 RegisterInputChannel`
用户据此问"qq 插件你没更新?"
## 查证:qq 没漏,是我的判据错了
- SDK 示例 `example/qq/plugin.go`:`RegisterOutputChannel("qq")` 在 368 行、
`RegisterInputChannel("qq", {NoMemory:true, Cleaner: inputCleaner})` 在 399 行 —— **先出站后入站**;
- 生产 `plugins/qq/plugin.bin`:版本 1.4.0,且二进制里含 `inputCleaner` 痕迹 ⇒ 确实调用了入站声明;
- 我的兜底告警在 **RegisterOutputChannel 的那一刻**判"有没有入站声明" ⇒ 对"先出站后入站"
这种完全合法的写法必然误报(a2a/acp/weather 同理)。
## 修法
告警判据从"注册时刻"改为"**插件 Start 结束后最终声明了什么**":
- `regOutput` 只保留兜底登记(功能不变),不再告警;
- 新增 `warnOutputOnlyChannels(plugin)`,在插件加载/重载成功后统一判定:
遍历该插件**最终**声明过的出站通道,只有始终没有对应入站声明的才告警,
且措辞改为"内核已兜底登记 inputch,若这是有意为之可忽略"。
- 判据与顺序解耦后,告警才代表真实缺口(例:weather 的 `weather_out` 与
`weather_in` 名字不同,出站名从未被声明为入站 —— 那条告警就是真的)。
## 验证
- 新增 `TestWarnOutputOnlyChannels`:①先出站后入站(qq 写法)**不告警**;
②只声明出站(weather 写法)**告警且只报那一个通道**。
- `go test ./internal/plugin/ ./internal/plugins/...` 全绿。
44 lines
1.4 KiB
Go
44 lines
1.4 KiB
Go
package plugin
|
||
|
||
import (
|
||
"bytes"
|
||
"log"
|
||
"strings"
|
||
"testing"
|
||
)
|
||
|
||
// 延迟判定的语义:看的是"插件 Start 结束后最终声明了什么",
|
||
// 而不是"注册出站通道的那一刻有没有入站声明"。
|
||
//
|
||
// 为什么必须这样判:声明顺序自由 —— qq/weather 都是**先** RegisterOutputChannel
|
||
// **后** RegisterInputChannel,按注册时刻判会把它们误报成"只声明了输出通道"
|
||
// (实测发生过:用户据此以为 qq 插件没更新)。
|
||
func TestWarnOutputOnlyChannels(t *testing.T) {
|
||
r := NewRegistry()
|
||
var buf bytes.Buffer
|
||
oldOut := log.Writer()
|
||
log.SetOutput(&buf)
|
||
defer log.SetOutput(oldOut)
|
||
|
||
// ① 出站+入站都声明了(先出站后入站)⇒ 不该告警
|
||
r.noteChannel("qq", "qq", true)
|
||
r.noteChannel("qq", "qq", false)
|
||
r.warnOutputOnlyChannels("qq")
|
||
if s := buf.String(); s != "" {
|
||
t.Fatalf("qq 声明了入站通道,不应告警,实际: %s", s)
|
||
}
|
||
|
||
// ② 只声明出站 ⇒ 应告警,且只报这一个通道
|
||
buf.Reset()
|
||
r.noteChannel("weather", "weather_weather_out", true)
|
||
r.noteChannel("weather", "weather_weather_in", false)
|
||
r.warnOutputOnlyChannels("weather")
|
||
out := buf.String()
|
||
if !strings.Contains(out, "weather_weather_out") {
|
||
t.Fatalf("只声明出站的通道应被告警,实际: %q", out)
|
||
}
|
||
if strings.Contains(out, "weather_weather_in") {
|
||
t.Fatalf("已声明入站的通道不该被牵连,实际: %q", out)
|
||
}
|
||
}
|