package openclaw import ( "bufio" "encoding/json" "fmt" "log" "os" "os/exec" "path/filepath" "sync" "time" ) type sidecarRequest struct { JSONRPC string `json:"jsonrpc"` ID int `json:"id"` Method string `json:"method"` Params interface{} `json:"params,omitempty"` } type sidecarResponse struct { JSONRPC string `json:"jsonrpc"` ID int `json:"id"` Result *json.RawMessage `json:"result,omitempty"` Error *struct { Code int `json:"code"` Message string `json:"message"` } `json:"error,omitempty"` } type OCPTool struct { Name string `json:"name"` Description string `json:"description"` InputSchema map[string]interface{} `json:"inputSchema"` } type OCCallResult struct { Content []struct { Type string `json:"type"` Text string `json:"text,omitempty"` } `json:"content"` } type sidecarProcess struct { name string dir string cmd *exec.Cmd stdin *bufio.Writer stdout *bufio.Scanner mu sync.Mutex nextID int closed bool stopped bool } func launchSidecar(dir, name string) (*sidecarProcess, error) { mainJS := filepath.Join(dir, "main.js") if _, err := os.Stat(mainJS); os.IsNotExist(err) { return nil, nil } return launchProcess("node", mainJS, dir, name) } func launchProcess(bin, arg, dir, name string) (*sidecarProcess, error) { nodePath := bin if bin == "node" { if p := os.Getenv("NODE_PATH"); p != "" { nodePath = filepath.Join(p, "node") } } // 将 dir(插件目录)作为最后一个参数传给 Node.js 进程 // 这样: node