package agent import ( "bytes" "encoding/json" "fmt" "net/http" "time" "github.com/ituoke/ituoke/internal/protocol" ) // ============================================================ // [Agent 桥] JSON-RPC HTTP 客户端(Go → Python) // Python 侧应对齐 protocol.Request / Response // 换 gRPC 时:保留 Service 方法,只替换本文件实现 // ============================================================ type Client struct { baseURL string httpClient *http.Client } func NewClient(addr string) *Client { return &Client{ baseURL: "http://" + addr, httpClient: &http.Client{ Timeout: 120 * time.Second, // 多模态可能较慢 }, } } // Call 发起版本化 JSON-RPC 风格请求 func (c *Client) Call(id, method string, params any) (*protocol.Response, error) { reqBody := protocol.Request{ ProtocolVersion: protocol.Version, ID: id, Method: method, Params: params, } raw, err := json.Marshal(reqBody) if err != nil { return nil, err } httpReq, err := http.NewRequest(http.MethodPost, c.baseURL+"/rpc", bytes.NewReader(raw)) if err != nil { return nil, err } httpReq.Header.Set("Content-Type", "application/json") httpRes, err := c.httpClient.Do(httpReq) if err != nil { return nil, fmt.Errorf("agent unreachable: %w", err) } defer httpRes.Body.Close() var res protocol.Response if err := json.NewDecoder(httpRes.Body).Decode(&res); err != nil { return nil, err } if res.Error != nil { return &res, fmt.Errorf("agent error %d: %s", res.Error.Code, res.Error.Message) } return &res, nil }