package main import ( "net" "strconv" "time" ) type ServiceProbe interface { Probe() []Service } type serviceProbeConfig struct { Name string Units []string Port int URL string } type SystemServiceProbe struct { services []serviceProbeConfig } func NewServiceProbe() ServiceProbe { return SystemServiceProbe{ services: []serviceProbeConfig{ {Name: "XWorkspace Console", Units: []string{"xworkspace-console.service"}, Port: 17000, URL: "http://127.0.0.1:17000"}, {Name: "OpenClaw Gateway", Units: []string{"xworkspace-openclaw.service", "openclaw-gateway.service"}, Port: 18789, URL: "http://127.0.0.1:18789/channels"}, {Name: "XWorkmate Bridge", Units: []string{"xworkspace-bridge.service", "xworkmate-bridge.service"}, Port: 8787, URL: "http://127.0.0.1:8787/api/ping"}, {Name: "AI Gateway Manager", Units: []string{"xworkspace-litellm.service", "litellm-proxy.service"}, Port: 4000, URL: "http://127.0.0.1:4000/ui"}, {Name: "Vault", Units: []string{"xworkspace-vault.service", "vault.service"}, Port: 8200, URL: "http://127.0.0.1:8200/ui/"}, {Name: "Terminal", Units: []string{"xworkspace-ttyd.service", "ttyd.service"}, Port: 7681, URL: "http://127.0.0.1:7681"}, }, } } func (p SystemServiceProbe) Probe() []Service { services := make([]Service, 0, len(p.services)) for _, config := range p.services { unit, state := firstSystemdUnit(config.Units) portOpen := config.Port > 0 && isPortOpen("127.0.0.1", config.Port) if state == "" && portOpen { state = "active" } else if state == "" { state = "inactive" } services = append(services, Service{ Name: config.Name, Unit: unit, State: state, Detail: probeDetail(unit, portOpen), Port: config.Port, URL: config.URL, }) } return services } func firstSystemdUnit(units []string) (string, string) { for _, unit := range units { if state := commandState("systemctl", "is-active", unit); state != "" && state != "unknown" { return unit, state } if state := commandState("systemctl", "--user", "is-active", unit); state != "" && state != "unknown" { return unit, state } } for _, unit := range units { if state := commandState("systemctl", "is-enabled", unit); state != "" && state != "unknown" { return unit, "" } if state := commandState("systemctl", "--user", "is-enabled", unit); state != "" && state != "unknown" { return unit, "" } } return "", "" } func probeDetail(unit string, portOpen bool) string { if unit == "" && portOpen { return "port open" } if portOpen { return "systemd + port open" } return "systemd" } func isPortOpen(host string, port int) bool { conn, err := net.DialTimeout("tcp", net.JoinHostPort(host, strconv.Itoa(port)), 300*time.Millisecond) if err != nil { return false } _ = conn.Close() return true }