Files
HomeAgent/internal/plugin/cabi/output_test.go
dev b74ee15321 fix(cabi): output_send 等待真实发送结果,消除假成功(plan 11.1 / Part 0.1)
根因:CORE_REGISTER_OUTPUT_CH handler 无条件返回 {status:queued}+err=nil,
模型永远收到「已发送」,实际失败(如 meta 缺 user_id)只写日志,模型无法感知不会重试。
现网近 7 天成功 44 次、失败 2 次全部谎报成功。

改动:
- loader.go: 新增 awaitOutputResult(+可注入版 awaitOutputResultWith)+ outputSendTimeout=10s
  goroutine 执行 cgo 发送 + 带超时 channel 等结果 → sent / error / unconfirmed 三态
  handler 由 executeOutputSendTool 从 Go 侧调起,非 cgo 栈,不构成 cgo 嵌套
- output.go: executeOutputSendTool 识别 unconfirmed|queued,回报「发送结果未确认」而非「已发送」
- output_test.go: Success/Failure/Timeout 三用例

验证: go build exit 0; go test ./internal/plugin/... ./internal/agent/... 全绿
接口冻结: git diff third_party/homeagent-sdk/sdk/ 为空
2026-08-31 12:16:39 +08:00

50 lines
1.4 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 cabi
import (
"errors"
"strings"
"testing"
"time"
)
// awaitOutputResult 的 decision 核心:
func TestAwaitOutputResult_Success(t *testing.T) {
res, err := awaitOutputResultWith(0, "qq", `{"x":1}`, func(pid int32, ch, args string) error {
return nil
}, outputSendTimeout)
if err != nil {
t.Fatalf("expected no error, got %v", err)
}
m, _ := res.(map[string]interface{})
if m["status"] != "sent" {
t.Fatalf("expected status=sent, got %v", m["status"])
}
}
func TestAwaitOutputResult_Failure(t *testing.T) {
_, err := awaitOutputResultWith(0, "qq", `{}`, func(pid int32, ch, args string) error {
return errors.New("meta 中需要 group_id 或 user_id 字段")
}, outputSendTimeout)
if err == nil {
t.Fatal("expected error on failed send, got nil (旧实现会谎报成功)")
}
if !strings.Contains(err.Error(), "需要 group_id") {
t.Fatalf("unexpected error: %v", err)
}
}
func TestAwaitOutputResult_Timeout(t *testing.T) {
res, err := awaitOutputResultWith(0, "qq", `{}`, func(pid int32, ch, args string) error {
time.Sleep(2 * time.Second) // 模拟插件发送迟迟不确认
return nil
}, 50*time.Millisecond)
if err != nil {
t.Fatalf("unconfirmed 不应返回 errorgot %v", err)
}
m, _ := res.(map[string]interface{})
if m["status"] != "unconfirmed" {
t.Fatalf("expected status=unconfirmed, got %v", m["status"])
}
}