package service import ( edgenode "iop/apps/edge/internal/node" "iop/packages/go/config" iop "iop/proto/gen/iop" ) // NodeSnapshot is a surface-neutral view of a registered node, suitable for // CLI, HTTP, or other transports. Label is the short display label (node0, node1). // AgentKind and LifecycleState carry the registry entry's generic node // classification and lifecycle. type NodeSnapshot struct { NodeID string Alias string Label string AgentKind string LifecycleState string Config *iop.NodeConfigPayload ProviderSnapshots []*iop.ProviderSnapshot } // ListNodeSnapshots returns surface-neutral node descriptors derived from the // current registry contents. func (s *Service) ListNodeSnapshots() []NodeSnapshot { entries := s.registry.All() store, _ := s.runtimeConfigSnapshot() out := make([]NodeSnapshot, 0, len(entries)) for _, entry := range entries { snap := NodeSnapshot{ NodeID: entry.NodeID, Alias: entry.Alias, Label: nodeLabel(entry), AgentKind: entry.AgentKind, LifecycleState: entry.LifecycleState, } var rec *edgenode.NodeRecord if store != nil { if r, ok := store.FindByID(entry.NodeID); ok { rec = r if payload, err := edgenode.BuildConfigPayload(r); err == nil { snap.Config = payload } } } if rec != nil { if s.queue != nil { snap.ProviderSnapshots = s.queue.getSnapshotForNode(entry.NodeID, rec) } else if len(rec.Providers) > 0 { snap.ProviderSnapshots = staticProviderCatalogSnapshots(rec) } } out = append(out, snap) } return out } // NodeEntrySnapshot converts a registry entry into the surface-neutral DTO. func NodeEntrySnapshot(entry *edgenode.NodeEntry) NodeSnapshot { if entry == nil { return NodeSnapshot{} } return NodeSnapshot{ NodeID: entry.NodeID, Alias: entry.Alias, Label: nodeLabel(entry), AgentKind: entry.AgentKind, LifecycleState: entry.LifecycleState, } } // staticProviderCatalogSnapshots builds catalog-based ProviderSnapshots with // zero inflight/queued for nodes whose config has a providers[] catalog but // whose service has no queue (e.g. queue disabled at startup). func staticProviderCatalogSnapshots(rec *edgenode.NodeRecord) []*iop.ProviderSnapshot { snaps := make([]*iop.ProviderSnapshot, 0, len(rec.Providers)) for _, prov := range rec.Providers { if prov.ID == "" { continue } servedModels := make([]string, len(prov.Models)) copy(servedModels, prov.Models) lifecycleCaps := make([]string, len(prov.LifecycleCapabilities)) copy(lifecycleCaps, prov.LifecycleCapabilities) if !config.ProviderEnabled(prov) { snaps = append(snaps, &iop.ProviderSnapshot{ Adapter: prov.Adapter, Status: "disabled", Capacity: 0, Id: prov.ID, Type: prov.Type, Category: string(prov.Category), ServedModels: servedModels, Health: "disabled", LifecycleCapabilities: lifecycleCaps, LongContextCapacity: 0, LongInFlight: 0, LongQueued: 0, }) continue } snaps = append(snaps, &iop.ProviderSnapshot{ Adapter: prov.Adapter, Status: "available", Capacity: int32(prov.Capacity), Id: prov.ID, Type: prov.Type, Category: string(prov.Category), ServedModels: servedModels, Health: prov.Health, LifecycleCapabilities: lifecycleCaps, LongContextCapacity: int32(prov.LongContextCapacity), LongInFlight: 0, LongQueued: 0, }) } return snaps } func (s *Service) ResolveNode(ref string) (*edgenode.NodeEntry, error) { return s.registry.Resolve(ref) } // ResolveNodeSnapshot returns a surface-neutral DTO for the resolved node. func (s *Service) ResolveNodeSnapshot(ref string) (NodeSnapshot, error) { entry, err := s.ResolveNode(ref) if err != nil { return NodeSnapshot{}, err } return NodeEntrySnapshot(entry), nil } func (s *Service) GetCapabilities() []*iop.EdgeCapabilitySummary { var entries []*edgenode.NodeEntry if s.registry != nil { entries = s.registry.All() } if len(entries) == 0 { return nil } return []*iop.EdgeCapabilitySummary{ { Kind: "run", Available: true, Status: "ready", Summary: "Generic execution node available", }, } } func (s *Service) GetDomainAgents() []*iop.EdgeDomainAgentSummary { return nil } // HealthStatusView is the Edge-owned status summary used by control commands // such as health.check. It is derived from the live node registry and // capability snapshot rather than a fixed simulation delay. type HealthStatusView struct { Nodes []NodeSnapshot Capabilities []*iop.EdgeCapabilitySummary } // HealthStatus returns a status summary derived from the current node registry // and capability snapshot. It is the real Edge-owned boundary that backs the // health.check control command. func (s *Service) HealthStatus() HealthStatusView { return HealthStatusView{ Nodes: s.ListNodeSnapshots(), Capabilities: s.GetCapabilities(), } }