package service import ( "context" "fmt" "sort" "strings" "time" iop "iop/proto/gen/iop" ) func edgeCommandResponseFromNodeCommand(req *iop.EdgeCommandRequest, view NodeCommandView, err error) *iop.EdgeCommandResponse { if err != nil { return &iop.EdgeCommandResponse{ Status: "error", Error: err.Error(), } } keys := make([]string, 0, len(view.Result)) for k := range view.Result { keys = append(keys, k) } sort.Strings(keys) summaries := make([]string, 0, len(keys)) for _, k := range keys { summaries = append(summaries, fmt.Sprintf("%s=%s", k, view.Result[k])) } summaryStr := fmt.Sprintf("NodeCommand %s completed: %s", req.GetParameters()["command"], strings.Join(summaries, ", ")) return &iop.EdgeCommandResponse{ Status: "completed", Summary: summaryStr, } } func unsupportedEdgeCommand(req *iop.EdgeCommandRequest, msg string) *iop.EdgeCommandResponse { return &iop.EdgeCommandResponse{ Status: "unsupported", Error: msg, } } func (s *Service) ExecuteCommand(ctx context.Context, req *iop.EdgeCommandRequest, onEvent func(*iop.EdgeCommandEvent)) (*iop.EdgeCommandResponse, error) { switch req.Operation { case "health.check": onEvent(&iop.EdgeCommandEvent{ CommandId: req.CommandId, Phase: "started", Summary: "Starting health check", OccurredAt: time.Now().UnixNano(), }) status := s.HealthStatus() summary := fmt.Sprintf("Edge health check OK: %d node(s), %d capability(ies)", len(status.Nodes), len(status.Capabilities)) onEvent(&iop.EdgeCommandEvent{ CommandId: req.CommandId, Phase: "completed", Summary: summary, OccurredAt: time.Now().UnixNano(), }) return &iop.EdgeCommandResponse{ Status: "completed", Summary: summary, }, nil case "agent.status": if req.TargetSelector == "" { return nil, fmt.Errorf("target_selector is required for agent.status") } onEvent(&iop.EdgeCommandEvent{ CommandId: req.CommandId, Phase: "started", Summary: fmt.Sprintf("Resolving agent status for %s", req.TargetSelector), OccurredAt: time.Now().UnixNano(), }) entry, err := s.ResolveNode(req.TargetSelector) if err != nil { return &iop.EdgeCommandResponse{ Status: "error", Error: err.Error(), }, nil } snap := NodeEntrySnapshot(entry) onEvent(&iop.EdgeCommandEvent{ CommandId: req.CommandId, Phase: "completed", Summary: fmt.Sprintf("Resolved agent status for %s", req.TargetSelector), OccurredAt: time.Now().UnixNano(), }) return &iop.EdgeCommandResponse{ Status: "completed", Summary: fmt.Sprintf("node ID=%s Alias=%s Kind=%s State=%s", snap.NodeID, snap.Alias, snap.AgentKind, snap.LifecycleState), }, nil case "agent.command": cmdName := req.GetParameters()["command"] if cmdName == "" { return unsupportedEdgeCommand(req, "missing command parameter for agent.command"), nil } onEvent(&iop.EdgeCommandEvent{ CommandId: req.CommandId, Phase: "started", Summary: fmt.Sprintf("Routing command %s to node %s", cmdName, req.TargetSelector), OccurredAt: time.Now().UnixNano(), }) entry, err := s.ResolveNode(req.TargetSelector) if err != nil { onEvent(&iop.EdgeCommandEvent{ CommandId: req.CommandId, Phase: "failed", Summary: fmt.Sprintf("Command %s failed: %v", cmdName, err), OccurredAt: time.Now().UnixNano(), }) return &iop.EdgeCommandResponse{ Status: "error", Error: err.Error(), }, nil } if entry.Client == nil { onEvent(&iop.EdgeCommandEvent{ CommandId: req.CommandId, Phase: "failed", Summary: fmt.Sprintf("Command %s failed: node client not connected", cmdName), OccurredAt: time.Now().UnixNano(), }) return &iop.EdgeCommandResponse{ Status: "error", Error: "node client not connected", }, nil } switch cmdName { case "capabilities": view, err := s.Capabilities(ctx, NodeCommandRequestSpec{ NodeRef: req.TargetSelector, Adapter: req.GetParameters()["adapter"], Target: req.GetParameters()["target"], SessionID: req.GetParameters()["session_id"], TimeoutSec: 10, }) var phase string var summary string if err != nil { phase = "failed" summary = fmt.Sprintf("Command %s failed: %v", cmdName, err) } else { phase = "completed" summary = fmt.Sprintf("Command %s completed successfully", cmdName) } onEvent(&iop.EdgeCommandEvent{ CommandId: req.CommandId, Phase: phase, Summary: summary, OccurredAt: time.Now().UnixNano(), }) return edgeCommandResponseFromNodeCommand(req, view, err), nil default: return unsupportedEdgeCommand(req, fmt.Sprintf("unsupported agent.command command %q", cmdName)), nil } default: return &iop.EdgeCommandResponse{ Status: "unsupported", Error: fmt.Sprintf("unsupported operation %s", req.Operation), }, nil } }