From a6489316f5b84523f76071bdde652fd9b1654434 Mon Sep 17 00:00:00 2001 From: Abir Abbas Date: Mon, 6 Jul 2026 19:25:12 -0400 Subject: [PATCH 1/4] feat(control-plane): add macOS menu-bar tray (af-tray) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Adds `af-tray`, a small separate binary that puts an AgentField icon in the macOS menu bar. It polls the control plane's public /health endpoint to show running/stopped status, opens the dashboard, and drives the control-plane lifecycle (start/stop/restart/start-at-login) via launchd — the tray is a controller of an OS service, not a supervisor. Design/isolation: - Separate binary so the systray/CGO dependency never enters the server binary (verified: ./cmd/af has no systray/dbus deps). Containers/headless hosts (Railway/ECS/EC2) never build, install, or run it. - Platform-neutral logic (health, launchd plist generation, launchctl arg construction, atomic writes) lives in shared.go with contract tests that run on the Linux CI; the systray loop and launchctl exec calls are darwin-tagged. Non-darwin builds compile a graceful no-op stub. - launchd semantics encode the intended behaviour: server uses KeepAlive={SuccessfulExit:false} so a graceful Stop sticks but a crash restarts; tray uses KeepAlive={Crashed:true} so Quit / no-GUI exit never crash-loops; server runs with --open=false under launchd. - install is idempotent/convergent (bootstrap + kickstart -k) so a `curl | bash` update force-restarts a stale tray/server onto the new binary with nothing manual. Co-Authored-By: Claude Opus 4.8 (1M context) --- .gitignore | 1 + control-plane/cmd/af-tray/assets/appicon.icns | Bin 0 -> 19839 bytes .../cmd/af-tray/assets/icon_active.ico | Bin 0 -> 58375 bytes .../cmd/af-tray/assets/icon_active.png | Bin 0 -> 1817 bytes .../cmd/af-tray/assets/icon_inactive.ico | Bin 0 -> 57207 bytes .../cmd/af-tray/assets/icon_inactive.png | Bin 0 -> 1610 bytes control-plane/cmd/af-tray/assets_darwin.go | 19 ++ control-plane/cmd/af-tray/launchd_darwin.go | 131 ++++++++ control-plane/cmd/af-tray/main.go | 73 +++++ control-plane/cmd/af-tray/shared.go | 228 ++++++++++++++ control-plane/cmd/af-tray/shared_test.go | 294 ++++++++++++++++++ control-plane/cmd/af-tray/tray_darwin.go | 129 ++++++++ control-plane/cmd/af-tray/tray_other.go | 29 ++ control-plane/go.mod | 2 + control-plane/go.sum | 4 + 15 files changed, 910 insertions(+) create mode 100644 control-plane/cmd/af-tray/assets/appicon.icns create mode 100644 control-plane/cmd/af-tray/assets/icon_active.ico create mode 100644 control-plane/cmd/af-tray/assets/icon_active.png create mode 100644 control-plane/cmd/af-tray/assets/icon_inactive.ico create mode 100644 control-plane/cmd/af-tray/assets/icon_inactive.png create mode 100644 control-plane/cmd/af-tray/assets_darwin.go create mode 100644 control-plane/cmd/af-tray/launchd_darwin.go create mode 100644 control-plane/cmd/af-tray/main.go create mode 100644 control-plane/cmd/af-tray/shared.go create mode 100644 control-plane/cmd/af-tray/shared_test.go create mode 100644 control-plane/cmd/af-tray/tray_darwin.go create mode 100644 control-plane/cmd/af-tray/tray_other.go diff --git a/.gitignore b/.gitignore index 9ea842be..0e0c7bf1 100644 --- a/.gitignore +++ b/.gitignore @@ -26,6 +26,7 @@ examples/go_agent_nodes/multi_version # Compiled binaries control-plane/agentfield-server control-plane/af +control-plane/af-tray scripts/lambda-rie-fake/lambda-rie-fake # Python diff --git a/control-plane/cmd/af-tray/assets/appicon.icns b/control-plane/cmd/af-tray/assets/appicon.icns new file mode 100644 index 0000000000000000000000000000000000000000..60a2f50efa441ffdcb799cda5385a3027065d99b GIT binary patch literal 19839 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 Xa}NG@K)S)B2L^y`F^SQg9Ip6pO7#^7 literal 0 HcmV?d00001 diff --git a/control-plane/cmd/af-tray/assets/icon_active.ico b/control-plane/cmd/af-tray/assets/icon_active.ico new file mode 100644 index 0000000000000000000000000000000000000000..3ff4b6780acda492249ae279159ee8f39c549c53 GIT binary patch literal 58375 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 Vm6bv7voa}xe2N5YtW6~ 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 W^<@D5T^~Tnf?hpWS1eI53;BNvWJ|XI literal 0 HcmV?d00001 diff --git a/control-plane/cmd/af-tray/assets/icon_active.png b/control-plane/cmd/af-tray/assets/icon_active.png new file mode 100644 index 0000000000000000000000000000000000000000..8c27b3311138e68e451ac38cf0759068d6f1c4ab GIT binary patch literal 1817 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 X+kaNz*Wdg_K0bV)bHD1IP2~RosD%HO literal 0 HcmV?d00001 diff --git a/control-plane/cmd/af-tray/assets/icon_inactive.png b/control-plane/cmd/af-tray/assets/icon_inactive.png new file mode 100644 index 0000000000000000000000000000000000000000..d26c62fa8c266a6f8deb63f76fc44688d2eb80c1 GIT binary patch literal 1610 zcmeAS@N?(olHy`uVBq!ia0vp^Iv~u!3?wz9Rv7~+mUKs7M+SzC{oH>NS%G|oWRD45bDP46hOx7_4S6Fo+k-*%fHRz`zt8;1l8sRG>BJfu^RW z1`vUOrj4~_Xs~}wWN2(uXk=KRk&&T`lS5-oNnd+iUq^j^M}1pkg|(H1wzhV5dSXvo zZEt&BOI?|jrG>t}UPVbxeN~aaua}#Plc|ZZgT1Y*i=&f+otdeLu8xkmnQ3)deqTpj zK~9>Xfq|Z$UV3tDM^jZ-OLb>+RYP@gQhZd9zjtj#L1%Mydt+ruL8gVdshO#zZb zfU45G#Mp?a@Zh|xl&J8akRZRN+S0C;8cPc^XGgo7jQE1=#N_x0U0q!dH)mrbLw!BH zlKc#7E6bYlg2LQ16BA<{ZEam$ow%rAZ%-Fn8>_VB*y^&psQ zI@sGJ#)jo)#Am0)Muz&gHdM4XRpwgnlvd%C40L?^~YIy>6? zc)7W|I=Q(z`FVQ))7AO~dF(*StR%=Un1O+j-y}F8F~n3rB=_k1zaNelh#BoUaQT{< z_`l*KCxt#*{)tRYi~3}B?6h#%{=7q2C;xiB7RX>P@$_|Nf5pxwWG?^i?dfn}>YnQ9;uvCadh6Af;X;8T3O`-pgLIjeMOlWccb&i(I;YJYE^CHeA%hVtj5 z)qKUz4!^&%v;X(K+Qh`kGE;KADq3ueJWecLl$;Wxur%rMvSZo-7Xo}{&zs;8xVX%1 zQpcCyPhR|=wbeMV!z1vQspxExQ%Y0jc=f9E1-BeqWnyP4I$7?Pl8JWn@rNISKIEA8 zD?jr%xXMTF^wNkH6Pvy%ZJSjRG!|q=aZfT>a7a`;d~Fc>iY8 z%{T3Q%rACJ%i8XBf5l;WtM1JYPN!GhGPR8}8U5xZtvy?Li|K*YWqyN%13%VeKe)4i zZ~pq71%VCvv1PY%V`38jx30dM*PPffW8KyZ*JUND1vsoY%y(5}72k7N7rov08lQHW zk8@f^;fxLL{7riq|CU!|m)~Q3Z;*Ja>V0L0#=idt;@#AD+%yZZueqYzC1_LkY0A>` z^Y%X|@Z9ryty;XmY{reWndLflZ@jbh}0NZDY$NkBMyC3+so~^apcGT^=LEhH7 zZze+Q-TNneoN0NsZ1#Pd`2Dr!e|}{CeERn-^L_dE_q9y;*x#r~?U3L8S>XGU#4i!7 zmKzS#E8S@9on*$fsZvHa^Td-UeLd@U27TCLBNxo6#aZ$1#F?c+;w{^_KmYwaGiX`M zrtT|?7sv0cI3&2%E1W$}Yh|W)k&9NiZtOOj`9gQXH}RA%Q`7dy*i`(PCH(f1Blc5^ z>$#7eC^`&Gv#KSo5hW>!C8<`)MX5lF!N|bKOxM6%*T5{q(89{p)XLaU+rYrez(C%k geL9MU-29Zxv`X9>@mff^V*UHx3vIVCg!08Hah^#A|> literal 0 HcmV?d00001 diff --git a/control-plane/cmd/af-tray/assets_darwin.go b/control-plane/cmd/af-tray/assets_darwin.go new file mode 100644 index 00000000..4e44d3c6 --- /dev/null +++ b/control-plane/cmd/af-tray/assets_darwin.go @@ -0,0 +1,19 @@ +package main + +import _ "embed" + +// Menu-bar icons. These are embedded on every platform (they are just bytes), +// but only referenced by the darwin tray implementation. Replace these with the +// final brand assets when available — icon_active is shown when the control +// plane is healthy, icon_inactive when it is stopped/unreachable. +// +//go:embed assets/icon_active.png +var iconActive []byte + +//go:embed assets/icon_inactive.png +var iconInactive []byte + +// appIconICNS is written into the generated .app bundle's Resources on macOS. +// +//go:embed assets/appicon.icns +var appIconICNS []byte diff --git a/control-plane/cmd/af-tray/launchd_darwin.go b/control-plane/cmd/af-tray/launchd_darwin.go new file mode 100644 index 00000000..74652bf7 --- /dev/null +++ b/control-plane/cmd/af-tray/launchd_darwin.go @@ -0,0 +1,131 @@ +//go:build darwin + +package main + +import ( + "fmt" + "os" + "os/exec" + "path/filepath" +) + +// ---- Install / uninstall --------------------------------------------------- + +// installDesktop is idempotent and convergent: every run rewrites the .app +// bundle and both launchd plists, then bootstraps-or-force-restarts each agent. +// This is what makes `curl … | install.sh` hands-off on both a fresh install +// and an update — a stale, already-running tray is killed and relaunched onto +// the freshly installed binary, and a freshly written agent is started now +// (not just at next login). +func installDesktop() error { + for _, d := range []string{logsDir(), launchAgentsDir(), + filepath.Join(appBundleDir(), "Contents", "MacOS"), + filepath.Join(appBundleDir(), "Contents", "Resources")} { + if err := os.MkdirAll(d, 0o755); err != nil { + return fmt.Errorf("mkdir %s: %w", d, err) + } + } + + // Build the .app bundle around a copy of ourselves. Using rename-over means + // we can safely replace the binary even while an old tray is executing it. + self, err := os.Executable() + if err != nil { + return fmt.Errorf("locate self: %w", err) + } + selfData, err := os.ReadFile(self) + if err != nil { + return fmt.Errorf("read self: %w", err) + } + if err := writeFileAtomic(trayBundleBinaryPath(), selfData, 0o755); err != nil { + return fmt.Errorf("install tray binary: %w", err) + } + if err := writeFileAtomic(filepath.Join(appBundleDir(), "Contents", "Resources", "appicon.icns"), appIconICNS, 0o644); err != nil { + return fmt.Errorf("write app icon: %w", err) + } + if err := writeFileAtomic(filepath.Join(appBundleDir(), "Contents", "Info.plist"), []byte(infoPlist()), 0o644); err != nil { + return fmt.Errorf("write Info.plist: %w", err) + } + + // launchd agents. + if err := writeFileAtomic(serverPlistPath(), []byte(serverPlist()), 0o644); err != nil { + return fmt.Errorf("write server plist: %w", err) + } + if err := writeFileAtomic(trayPlistPath(), []byte(trayPlist()), 0o644); err != nil { + return fmt.Errorf("write tray plist: %w", err) + } + + // Converge launchd state. bootstrap is ignored if already loaded; the + // kickstart -k then force-restarts onto the new binary in every case. + _ = bootstrapAgent(serverPlistPath()) + _ = kickstartAgent(serverLabel, true) + _ = bootstrapAgent(trayPlistPath()) + _ = kickstartAgent(trayLabel, true) + + fmt.Println("AgentField desktop tray installed. Look for the icon in your menu bar.") + return nil +} + +func uninstallDesktop() error { + _ = bootoutAgent(trayLabel) + _ = bootoutAgent(serverLabel) + _ = os.Remove(trayPlistPath()) + _ = os.Remove(serverPlistPath()) + _ = os.RemoveAll(appBundleDir()) + fmt.Println("AgentField desktop tray removed.") + return nil +} + +// ---- Server lifecycle (driven from the tray menu) -------------------------- + +func startServer() error { + if !agentLoaded(serverLabel) { + _ = bootstrapAgent(serverPlistPath()) + } + return kickstartAgent(serverLabel, false) +} + +// stopServer sends SIGTERM for a graceful shutdown. Because the server plist +// uses KeepAlive={SuccessfulExit: false}, a clean exit is not relaunched — so +// "Stop" actually stops it, while a genuine crash still auto-restarts. +func stopServer() error { + return exec.Command("launchctl", "kill", "SIGTERM", svcTarget(serverLabel)).Run() +} + +func restartServer() error { + if !agentLoaded(serverLabel) { + _ = bootstrapAgent(serverPlistPath()) + } + return kickstartAgent(serverLabel, true) +} + +// serverAutostartEnabled reflects whether the server agent is loaded (and will +// therefore start at login). +func serverAutostartEnabled() bool { return agentLoaded(serverLabel) } + +func setServerAutostart(enable bool) error { + if enable { + if err := bootstrapAgent(serverPlistPath()); err != nil && !agentLoaded(serverLabel) { + return err + } + return kickstartAgent(serverLabel, false) + } + return bootoutAgent(serverLabel) +} + +// ---- launchctl exec wrappers ----------------------------------------------- + +func bootstrapAgent(plistPath string) error { + return exec.Command("launchctl", "bootstrap", guiDomain(), plistPath).Run() +} + +func bootoutAgent(label string) error { + return exec.Command("launchctl", "bootout", svcTarget(label)).Run() +} + +func kickstartAgent(label string, kill bool) error { + return exec.Command("launchctl", kickstartArgs(label, kill)...).Run() +} + +func agentLoaded(label string) bool { + return exec.Command("launchctl", "print", svcTarget(label)).Run() == nil +} diff --git a/control-plane/cmd/af-tray/main.go b/control-plane/cmd/af-tray/main.go new file mode 100644 index 00000000..4ff6d5d7 --- /dev/null +++ b/control-plane/cmd/af-tray/main.go @@ -0,0 +1,73 @@ +// Command af-tray is the AgentField menu-bar companion. +// +// It is a small, separate binary from the main `af`/agentfield control-plane +// binary on purpose: it carries the GUI/systray dependency so the server binary +// never has to. In a headless deployment (Railway, ECS, EC2, a container) the +// tray simply is never installed or run — and if it is run there anyway, it +// detects the absence of a GUI session and exits cleanly instead of crashing. +// +// Subcommands: +// +// af-tray run Run the menu-bar tray (default). +// af-tray install Install the desktop tray + control-plane autostart (macOS). +// af-tray uninstall Remove the desktop tray and autostart. +// af-tray version Print version. +// +// The platform-specific behaviour lives in tray_darwin.go / launchd_darwin.go +// (real implementation) and tray_other.go (no-op stubs for every other OS). +package main + +import ( + "fmt" + "os" +) + +// Build-time version information (set via ldflags during build). +var ( + version = "dev" + commit = "none" + date = "unknown" +) + +func main() { + cmd := "run" + if len(os.Args) > 1 { + cmd = os.Args[1] + } + + switch cmd { + case "run": + if err := runTray(); err != nil { + fmt.Fprintln(os.Stderr, "af-tray:", err) + os.Exit(1) + } + case "install": + if err := installDesktop(); err != nil { + fmt.Fprintln(os.Stderr, "af-tray install:", err) + os.Exit(1) + } + case "uninstall": + if err := uninstallDesktop(); err != nil { + fmt.Fprintln(os.Stderr, "af-tray uninstall:", err) + os.Exit(1) + } + case "version", "--version", "-v": + fmt.Printf("af-tray %s (%s) %s\n", version, commit, date) + case "help", "--help", "-h": + printUsage() + default: + printUsage() + os.Exit(2) + } +} + +func printUsage() { + fmt.Print(`af-tray — AgentField menu-bar companion + +Usage: + af-tray run Run the menu-bar tray (default) + af-tray install Install the desktop tray + control-plane autostart (macOS) + af-tray uninstall Remove the desktop tray and control-plane autostart + af-tray version Print version information +`) +} diff --git a/control-plane/cmd/af-tray/shared.go b/control-plane/cmd/af-tray/shared.go new file mode 100644 index 00000000..2fdd2912 --- /dev/null +++ b/control-plane/cmd/af-tray/shared.go @@ -0,0 +1,228 @@ +package main + +// This file holds the platform-neutral logic behind the tray: health polling, +// path resolution, launchd plist / Info.plist generation, launchctl argument +// construction, and atomic file writes. It has NO GUI (systray/CGO) dependency +// and compiles on every platform, so it can be unit-tested directly in CI +// (which runs on Linux). The OS-specific glue — the systray event loop and the +// exec.Command("launchctl", …) calls — lives in the _darwin files and calls +// into these helpers. + +import ( + "fmt" + "net/http" + "os" + "os/exec" + "path/filepath" + "strconv" + "time" +) + +const ( + trayLabel = "ai.agentfield.tray" + serverLabel = "ai.agentfield.server" +) + +// ---- Paths ----------------------------------------------------------------- + +func home() string { + h, _ := os.UserHomeDir() + return h +} + +func agentfieldDir() string { return filepath.Join(home(), ".agentfield") } +func binDir() string { return filepath.Join(agentfieldDir(), "bin") } +func logsDir() string { return filepath.Join(agentfieldDir(), "logs") } +func launchAgentsDir() string { return filepath.Join(home(), "Library", "LaunchAgents") } +func appBundleDir() string { return filepath.Join(home(), "Applications", "AgentField.app") } +func serverLogPath() string { return filepath.Join(logsDir(), "control-plane.log") } +func trayLogPath() string { return filepath.Join(logsDir(), "tray.log") } +func trayPlistPath() string { return filepath.Join(launchAgentsDir(), trayLabel+".plist") } +func serverPlistPath() string { return filepath.Join(launchAgentsDir(), serverLabel+".plist") } + +func trayBundleBinaryPath() string { + return filepath.Join(appBundleDir(), "Contents", "MacOS", "af-tray") +} + +// serverBinaryPath finds the control-plane binary the launchd agent should run. +// It prefers the installed copy, then falls back to whatever is on PATH. +func serverBinaryPath() string { + cand := filepath.Join(binDir(), "agentfield") + if isExecutable(cand) { + return cand + } + if p, err := exec.LookPath("af"); err == nil { + return p + } + if p, err := exec.LookPath("agentfield"); err == nil { + return p + } + return cand // best effort; may not exist yet. +} + +func isExecutable(path string) bool { + info, err := os.Stat(path) + if err != nil { + return false + } + return !info.IsDir() && info.Mode()&0o111 != 0 +} + +// ---- Health / URLs --------------------------------------------------------- + +// serverPort returns the port the control plane is expected to listen on. +func serverPort() int { + if v := os.Getenv("AGENTFIELD_PORT"); v != "" { + if p, err := strconv.Atoi(v); err == nil { + return p + } + } + return 8080 +} + +func healthURL() string { return fmt.Sprintf("http://localhost:%d/health", serverPort()) } +func dashboardURL() string { return fmt.Sprintf("http://localhost:%d", serverPort()) } + +// checkHealth reports whether the given URL answers HTTP 200 within a short +// timeout. The control plane's /health endpoint returns 200 when healthy and +// 503 when not, so only a 200 counts as "running". +func checkHealth(url string) bool { + client := &http.Client{Timeout: 2 * time.Second} + resp, err := client.Get(url) + if err != nil { + return false + } + defer func() { _ = resp.Body.Close() }() + return resp.StatusCode == http.StatusOK +} + +func serverHealthy() bool { return checkHealth(healthURL()) } + +// ---- launchctl argument construction --------------------------------------- + +func guiDomain() string { return fmt.Sprintf("gui/%d", os.Getuid()) } +func svcTarget(l string) string { return guiDomain() + "/" + l } + +// kickstartArgs builds the argv for `launchctl kickstart`. The -k flag forces a +// restart of an already-running service (kill then relaunch); without it, +// kickstart only starts a loaded-but-idle service. +func kickstartArgs(label string, kill bool) []string { + args := []string{"kickstart"} + if kill { + args = append(args, "-k") + } + return append(args, svcTarget(label)) +} + +// ---- Files ----------------------------------------------------------------- + +// writeFileAtomic writes data to a temp file in the destination directory and +// renames it into place, so a reader (or a running binary being replaced) never +// sees a half-written file. +func writeFileAtomic(path string, data []byte, perm os.FileMode) error { + dir := filepath.Dir(path) + if err := os.MkdirAll(dir, 0o755); err != nil { + return err + } + tmp, err := os.CreateTemp(dir, ".af-tray-*") + if err != nil { + return err + } + tmpName := tmp.Name() + if _, err := tmp.Write(data); err != nil { + _ = tmp.Close() + _ = os.Remove(tmpName) + return err + } + if err := tmp.Close(); err != nil { + _ = os.Remove(tmpName) + return err + } + if err := os.Chmod(tmpName, perm); err != nil { + _ = os.Remove(tmpName) + return err + } + return os.Rename(tmpName, path) +} + +// ---- plist / Info.plist templates ------------------------------------------ + +func infoPlist() string { + return fmt.Sprintf(` + + + + CFBundleNameAgentField + CFBundleDisplayNameAgentField + CFBundleIdentifier%s + CFBundleVersion%s + CFBundleShortVersionString%s + CFBundlePackageTypeAPPL + CFBundleExecutableaf-tray + CFBundleIconFileappicon + LSUIElement + LSMinimumSystemVersion10.15 + + +`, trayLabel, version, version) +} + +// serverPlist is the control-plane launchd agent. +// - RunAtLoad starts it at login. +// - KeepAlive={SuccessfulExit: false} restarts it only on a crash, so a +// graceful "Stop" (SIGTERM → clean exit) actually stays stopped. +// - --open=false stops it opening a browser every time it starts under launchd. +func serverPlist() string { + log := serverLogPath() + return fmt.Sprintf(` + + + + Label%s + ProgramArguments + + %s + server + --open=false + + RunAtLoad + KeepAlive + SuccessfulExit + WorkingDirectory%s + StandardOutPath%s + StandardErrorPath%s + EnvironmentVariables + + PATH/opt/homebrew/bin:/usr/local/bin:/usr/bin:/bin:/usr/sbin:/sbin + + ProcessTypeBackground + + +`, serverLabel, serverBinaryPath(), agentfieldDir(), log, log) +} + +// trayPlist is the menu-bar tray launchd agent. KeepAlive={Crashed: true} means +// a genuine crash relaunches it, but a clean exit (the "Quit" menu item, or the +// no-GUI-session early exit) does not — so it never crash-loops. +func trayPlist() string { + log := trayLogPath() + return fmt.Sprintf(` + + + + Label%s + ProgramArguments + + %s + run + + RunAtLoad + KeepAlive + Crashed + StandardOutPath%s + StandardErrorPath%s + ProcessTypeInteractive + + +`, trayLabel, trayBundleBinaryPath(), log, log) +} diff --git a/control-plane/cmd/af-tray/shared_test.go b/control-plane/cmd/af-tray/shared_test.go new file mode 100644 index 00000000..0193f8e7 --- /dev/null +++ b/control-plane/cmd/af-tray/shared_test.go @@ -0,0 +1,294 @@ +package main + +import ( + "net/http" + "net/http/httptest" + "net/url" + "os" + "path/filepath" + "strings" + "testing" +) + +// These tests validate the behaviours the tray depends on, expressed as +// contracts rather than by mirroring the implementation. They live in a +// build-tag-free file so they compile and run on the Linux CI even though the +// tray UI itself is macOS-only. + +// Contract: the port comes from AGENTFIELD_PORT when set to a valid integer, +// and defaults to 8080 otherwise (including when the value is garbage). +func TestServerPort(t *testing.T) { + cases := []struct { + name string + env string + set bool + want int + }{ + {"default when unset", "", false, 8080}, + {"honors valid env", "9090", true, 9090}, + {"falls back on garbage", "not-a-number", true, 8080}, + {"falls back on empty", "", true, 8080}, + } + for _, tc := range cases { + t.Run(tc.name, func(t *testing.T) { + if tc.set { + t.Setenv("AGENTFIELD_PORT", tc.env) + } else { + _ = os.Unsetenv("AGENTFIELD_PORT") + } + if got := serverPort(); got != tc.want { + t.Fatalf("serverPort() = %d, want %d", got, tc.want) + } + }) + } +} + +// Contract: the health/dashboard URLs target the resolved port on localhost. +func TestURLsUsePort(t *testing.T) { + t.Setenv("AGENTFIELD_PORT", "1234") + if got, want := healthURL(), "http://localhost:1234/health"; got != want { + t.Errorf("healthURL() = %q, want %q", got, want) + } + if got, want := dashboardURL(), "http://localhost:1234"; got != want { + t.Errorf("dashboardURL() = %q, want %q", got, want) + } +} + +// Contract: a server is "running" only when /health answers HTTP 200; a 503 +// (unhealthy) or an unreachable server both read as not running. +func TestCheckHealth(t *testing.T) { + ok := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, _ *http.Request) { + w.WriteHeader(http.StatusOK) + })) + defer ok.Close() + if !checkHealth(ok.URL) { + t.Error("checkHealth on a 200 server = false, want true") + } + + unhealthy := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, _ *http.Request) { + w.WriteHeader(http.StatusServiceUnavailable) + })) + defer unhealthy.Close() + if checkHealth(unhealthy.URL) { + t.Error("checkHealth on a 503 server = true, want false") + } + + // Unreachable: start a server, capture its URL, then close it. + down := httptest.NewServer(http.HandlerFunc(func(http.ResponseWriter, *http.Request) {})) + downURL := down.URL + down.Close() + if checkHealth(downURL) { + t.Error("checkHealth on a closed server = true, want false") + } +} + +// Contract: serverHealthy() wires serverPort()→healthURL()→checkHealth end to +// end against a live server. +func TestServerHealthyEndToEnd(t *testing.T) { + ts := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { + if r.URL.Path == "/health" { + w.WriteHeader(http.StatusOK) + return + } + w.WriteHeader(http.StatusNotFound) + })) + defer ts.Close() + + u, err := url.Parse(ts.URL) + if err != nil { + t.Fatal(err) + } + t.Setenv("AGENTFIELD_PORT", u.Port()) // localhost: resolves to the test server. + if !serverHealthy() { + t.Error("serverHealthy() = false against a live /health, want true") + } +} + +// Contract: kickstart uses -k (force restart) only when a kill is requested, +// and always targets gui//