feat: complete OpenClaw plugin API bridge with async notification architecture

- simulator/main.js: All 30+ register* methods now send JSON-RPC notifications
  to Go instead of being silent no-ops. Each plugin capability registration
  (tool, provider, channel, hook, http_route, command, service, etc.) is
  forwarded to Go via the notify channel.

- sidecar.go: Refactored to async reader goroutine. Single goroutine reads
  all stdout lines, routes responses to pending callers via channel by ID,
  and dispatches notifications (no-ID messages) to notifyCh for handling.

- plugin.go: drainNotify() collects all capabilities registered during
  plugin init. handleNotify() logs each registered capability for visibility.

- All 9 openclaw tests pass including simulator + full pipeline tests.
This commit is contained in:
root
2026-07-04 14:08:42 +08:00
parent 4102c6b034
commit e273e746ea
3 changed files with 276 additions and 107 deletions

View File

@ -142,6 +142,9 @@ func (p *Plugin) loadOCPlugin(s *sdk.PluginSDK, dir, name string) error {
return nil
}
// 收集插件注册过程中模拟器推送的通知
p.drainNotify(sp, name)
tools, err := sp.ListTools()
if err != nil {
sp.Close()
@ -174,6 +177,37 @@ func (p *Plugin) loadOCPlugin(s *sdk.PluginSDK, dir, name string) error {
return nil
}
func (p *Plugin) drainNotify(sp *sidecarProcess, name string) {
for {
select {
case n := <-sp.NotifyChan():
p.handleNotify(n, name)
default:
return
}
}
}
func (p *Plugin) handleNotify(n OCNotification, name string) {
if n.Method != "register" {
log.Printf("[openclaw] ocplugin %s: unknown notify method: %s", name, n.Method)
return
}
var params struct {
Type string `json:"type"`
Data json.RawMessage `json:"data"`
}
if err := json.Unmarshal(n.Params, &params); err != nil {
log.Printf("[openclaw] ocplugin %s: bad notify params: %v", name, err)
return
}
dataStr := string(params.Data)
if len(dataStr) > 200 {
dataStr = dataStr[:200] + "..."
}
log.Printf("[openclaw] ocplugin %s: capability %s data=%s", name, params.Type, dataStr)
}
func (p *Plugin) loadSidecar(s *sdk.PluginSDK, dir, name string) error {
sp, err := launchSidecar(dir, name)
if err != nil {