clawhubadapter: OpenClaw 通道插件兼容修复(gateway 生命周期桥 + channelRuntime + deliver 事件式输出)

- manager/main.js:makeChannelRuntime(dispatchReplyWithBufferedBlockDispatcher 入站 + deliver 出站
  绑定 + typingCallbacks)、startChannels/stopChannels(gateway.startAccount fire-and-forget 生命周期
  桥、listAccountIds/resolveAccount 规范签名 cfg 传参)、tools/call 通道分支无 outbound 走 deliver
  事件式发送、SIGTERM 优雅停靠、console 输出重定向 stderr 防 JSON-RPC 流污染
- plugin.go:channel_input 改 InjectInputSync 同步注入取回复并经 CallTool 回发通道(修复
  InjectInterruptText 无 ResponseCh 致回复静默丢弃);channel_status/channel_output 通知接入
- registry.go:channelStatus 状态缓存
- SDK:公共 IOInjector 增加 InjectInputSync(source, channel, text) string + ioAdapter 实现
- 生产验证:微信发消息 → pollLoop → dispatchReply → mock LLM 回文本 → deliver →
  ilink/bot/sendmessage status=200 送达
This commit is contained in:
root
2026-08-02 13:03:49 +08:00
parent c7ee45d6e1
commit 76ef49e9a6
5 changed files with 277 additions and 8 deletions

View File

@ -748,7 +748,60 @@ func (p *Plugin) translateAndRegister(n OCNotification, sp *sidecarProcess, s *s
data, _ := json.Marshal(params.Payload)
content = string(data)
}
s.InjectInterruptText(pluginName, params.Channel, fmt.Sprintf("[%s] %s", params.Channel, content))
// 同步注入并取回复再把回复送回通道agent → output_send__<通道> → deliver → 微信)
out := s.InjectInputSync(pluginName, params.Channel, "text", map[string]interface{}{
"content": content,
})
if out != nil {
reply, _ := out.Payload["content"].(string)
if reply != "" {
meta := map[string]interface{}{}
if from, _ := params.Payload["from"].(string); from != "" {
meta["user_id"] = from
}
if acc, _ := params.Payload["accountId"].(string); acc != "" {
meta["accountId"] = acc
}
go func() {
if _, err := sp.CallTool(params.Channel, map[string]interface{}{
"payload": reply,
"meta": meta,
}); err != nil {
log.Printf("[clawhubadapter] channel %s reply dispatch failed: %v", params.Channel, err)
}
}()
}
}
return
}
if n.Method == "channel_status" {
var params struct {
Channel string `json:"channel"`
Status map[string]interface{} `json:"status"`
}
if err := json.Unmarshal(n.Params, &params); err != nil || params.Channel == "" {
return
}
channelStatusMu.Lock()
if channelStatus == nil {
channelStatus = make(map[string]map[string]interface{})
}
channelStatus[params.Channel] = params.Status
channelStatusMu.Unlock()
log.Printf("[clawhubadapter] channel_status %s: running=%v connected=%v", params.Channel,
params.Status["running"], params.Status["connected"])
return
}
if n.Method == "channel_output" {
// 降级输出事件(通道已启动但 deliver 尚未建立):仅记录,消息不丢失于协议层
var params struct {
Channel string `json:"channel"`
Type string `json:"type"`
Text string `json:"text"`
}
if json.Unmarshal(n.Params, &params) == nil && params.Channel != "" {
log.Printf("[clawhubadapter] channel_output %s (type=%s): %.120s", params.Channel, params.Type, params.Text)
}
return
}
if n.Method != "register" {