mirror of
https://github.com/YspCoder/clawgo.git
synced 2026-04-14 18:17:29 +08:00
enhance device-operation routing with action paths and nodes tool shortcuts
This commit is contained in:
@@ -78,9 +78,24 @@ func NewAgentLoop(cfg *config.Config, msgBus *bus.MessageBus, provider providers
|
||||
toolsRegistry.Register(tools.NewExecTool(cfg.Tools.Shell, workspace, processManager))
|
||||
toolsRegistry.Register(tools.NewProcessTool(processManager))
|
||||
nodesManager := nodes.NewManager()
|
||||
nodesManager.Upsert(nodes.NodeInfo{ID: "local", Name: "local", Capabilities: nodes.Capabilities{Run: true, Invoke: true}, Online: true})
|
||||
nodesManager.Upsert(nodes.NodeInfo{ID: "local", Name: "local", Capabilities: nodes.Capabilities{Run: true, Invoke: true, Camera: true, Screen: true, Location: true, Canvas: true}, Online: true})
|
||||
nodesManager.RegisterHandler("local", func(req nodes.Request) nodes.Response {
|
||||
return nodes.Response{OK: true, Node: "local", Action: req.Action, Payload: map[string]interface{}{"echo": req.Args, "transport": "relay-local"}}
|
||||
switch req.Action {
|
||||
case "run":
|
||||
payload := map[string]interface{}{"transport": "relay-local"}
|
||||
if cmdRaw, ok := req.Args["command"].([]interface{}); ok && len(cmdRaw) > 0 {
|
||||
parts := make([]string, 0, len(cmdRaw))
|
||||
for _, x := range cmdRaw {
|
||||
parts = append(parts, fmt.Sprint(x))
|
||||
}
|
||||
payload["command"] = parts
|
||||
}
|
||||
return nodes.Response{OK: true, Node: "local", Action: req.Action, Payload: payload}
|
||||
case "camera_snap", "camera_clip", "screen_record", "screen_snapshot", "location_get", "canvas_snapshot", "canvas_action":
|
||||
return nodes.Response{OK: true, Node: "local", Action: req.Action, Payload: map[string]interface{}{"transport": "relay-local", "simulated": true, "args": req.Args}}
|
||||
default:
|
||||
return nodes.Response{OK: true, Node: "local", Action: req.Action, Payload: map[string]interface{}{"echo": req.Args, "transport": "relay-local"}}
|
||||
}
|
||||
})
|
||||
nodesRouter := &nodes.Router{P2P: &nodes.StubP2PTransport{}, Relay: &nodes.HTTPRelayTransport{Manager: nodesManager}}
|
||||
toolsRegistry.Register(tools.NewNodesTool(nodesManager, nodesRouter))
|
||||
|
||||
@@ -68,6 +68,32 @@ type HTTPRelayTransport struct {
|
||||
}
|
||||
|
||||
func (s *HTTPRelayTransport) Name() string { return "relay" }
|
||||
|
||||
func actionHTTPPath(action string) string {
|
||||
switch strings.ToLower(strings.TrimSpace(action)) {
|
||||
case "run":
|
||||
return "/run"
|
||||
case "invoke":
|
||||
return "/invoke"
|
||||
case "camera_snap":
|
||||
return "/camera/snap"
|
||||
case "camera_clip":
|
||||
return "/camera/clip"
|
||||
case "screen_record":
|
||||
return "/screen/record"
|
||||
case "screen_snapshot":
|
||||
return "/screen/snapshot"
|
||||
case "location_get":
|
||||
return "/location/get"
|
||||
case "canvas_snapshot":
|
||||
return "/canvas/snapshot"
|
||||
case "canvas_action":
|
||||
return "/canvas/action"
|
||||
default:
|
||||
return "/invoke"
|
||||
}
|
||||
}
|
||||
|
||||
func (s *HTTPRelayTransport) Send(ctx context.Context, req Request) (Response, error) {
|
||||
if s.Manager == nil {
|
||||
return Response{OK: false, Node: req.Node, Action: req.Action, Error: "relay manager not configured"}, nil
|
||||
@@ -88,7 +114,8 @@ func (s *HTTPRelayTransport) Send(ctx context.Context, req Request) (Response, e
|
||||
client = &http.Client{Timeout: 20 * time.Second}
|
||||
}
|
||||
body, _ := json.Marshal(req)
|
||||
hreq, err := http.NewRequestWithContext(ctx, http.MethodPost, endpoint+"/invoke", bytes.NewReader(body))
|
||||
path := actionHTTPPath(req.Action)
|
||||
hreq, err := http.NewRequestWithContext(ctx, http.MethodPost, endpoint+path, bytes.NewReader(body))
|
||||
if err != nil {
|
||||
return Response{}, err
|
||||
}
|
||||
|
||||
@@ -18,14 +18,17 @@ type NodesTool struct {
|
||||
func NewNodesTool(m *nodes.Manager, r *nodes.Router) *NodesTool { return &NodesTool{manager: m, router: r} }
|
||||
func (t *NodesTool) Name() string { return "nodes" }
|
||||
func (t *NodesTool) Description() string {
|
||||
return "Manage paired nodes (status/describe/run/invoke/camera/screen/location)."
|
||||
return "Manage paired nodes (status/describe/run/invoke/camera/screen/location/canvas)."
|
||||
}
|
||||
func (t *NodesTool) Parameters() map[string]interface{} {
|
||||
return map[string]interface{}{"type": "object", "properties": map[string]interface{}{
|
||||
"action": map[string]interface{}{"type": "string", "description": "status|describe|run|invoke|camera_snap|screen_record|location_get"},
|
||||
"action": map[string]interface{}{"type": "string", "description": "status|describe|run|invoke|camera_snap|camera_clip|screen_record|screen_snapshot|location_get|canvas_snapshot|canvas_action"},
|
||||
"node": map[string]interface{}{"type": "string", "description": "target node id"},
|
||||
"mode": map[string]interface{}{"type": "string", "description": "auto|p2p|relay (default auto)"},
|
||||
"args": map[string]interface{}{"type": "object", "description": "action args"},
|
||||
"command": map[string]interface{}{"type": "array", "description": "run command array shortcut"},
|
||||
"facing": map[string]interface{}{"type": "string", "description": "camera facing: front|back|both"},
|
||||
"duration_ms": map[string]interface{}{"type": "integer", "description": "clip/record duration"},
|
||||
}, "required": []string{"action"}}
|
||||
}
|
||||
|
||||
@@ -66,9 +69,20 @@ func (t *NodesTool) Execute(ctx context.Context, args map[string]interface{}) (s
|
||||
if t.router == nil {
|
||||
return "", fmt.Errorf("nodes transport router not configured")
|
||||
}
|
||||
var reqArgs map[string]interface{}
|
||||
reqArgs := map[string]interface{}{}
|
||||
if raw, ok := args["args"].(map[string]interface{}); ok {
|
||||
reqArgs = raw
|
||||
for k, v := range raw {
|
||||
reqArgs[k] = v
|
||||
}
|
||||
}
|
||||
if cmd, ok := args["command"].([]interface{}); ok && len(cmd) > 0 {
|
||||
reqArgs["command"] = cmd
|
||||
}
|
||||
if facing, _ := args["facing"].(string); strings.TrimSpace(facing) != "" {
|
||||
reqArgs["facing"] = strings.TrimSpace(facing)
|
||||
}
|
||||
if d, ok := args["duration_ms"].(float64); ok && d > 0 {
|
||||
reqArgs["duration_ms"] = int(d)
|
||||
}
|
||||
resp, err := t.router.Dispatch(ctx, nodes.Request{Action: action, Node: nodeID, Args: reqArgs}, mode)
|
||||
if err != nil {
|
||||
|
||||
Reference in New Issue
Block a user