From a838adcb277a41efddafc69373312b3d54878b65 Mon Sep 17 00:00:00 2001 From: Mitchell-Johnson Date: Sat, 19 Sep 2026 10:45:24 -0700 Subject: [PATCH] Machine menu shows each machine's address instead of its load Co-Authored-By: Claude Fable 5.1 --- internal/api/server.go | 11 ++++++++--- web/src/MachineSwitcher.tsx | 10 ++++++---- web/src/Shell.tsx | 2 +- web/src/api.ts | 2 +- 4 files changed, 16 insertions(+), 9 deletions(-) diff --git a/internal/api/server.go b/internal/api/server.go index bfa2298..48375cc 100644 --- a/internal/api/server.go +++ b/internal/api/server.go @@ -745,12 +745,17 @@ func (s *Server) me(w http.ResponseWriter, _ *http.Request) { } } _, rebootErr := os.Stat("/run/reboot-required") - var demoURL string - s.cfg.View(func(c *config.Config) { demoURL = c.DemoURL }) + var demoURL, addr string + s.cfg.View(func(c *config.Config) { + demoURL = c.DemoURL + if h, _, err := net.SplitHostPort(c.Listen); err == nil && h != "" && h != "0.0.0.0" && h != "::" { + addr = h // the address this console listens on, for the machine menu + } + }) jsonOK(w, 200, map[string]any{ "host": s.host, "user": s.user, "version": s.version, "load": load, "uptime": uptime, "service_started": s.started, - "reboot_needed": rebootErr == nil, "fingerprint": s.fingerprint, "arch": runtime.GOARCH, "demo_url": demoURL, + "reboot_needed": rebootErr == nil, "fingerprint": s.fingerprint, "arch": runtime.GOARCH, "demo_url": demoURL, "addr": addr, }) } diff --git a/web/src/MachineSwitcher.tsx b/web/src/MachineSwitcher.tsx index 4ad1d13..4fcacf3 100644 --- a/web/src/MachineSwitcher.tsx +++ b/web/src/MachineSwitcher.tsx @@ -2,10 +2,12 @@ import { useEffect, useRef, useState } from 'react' import { MachineStatus } from './api' import { useEscape } from './ui' +const hostOf = (url: string) => { try { return new URL(url).hostname } catch { return url } } + // The host picker at the top of the rail. The hub is always first; managed machines follow // with their live status. Picking one re-points the whole console at it. -export default function MachineSwitcher({ hub, current, machines, onChange, onManage }: { - hub: string; current: string | null; machines: MachineStatus[]; onChange: (name: string | null) => void; onManage: () => void +export default function MachineSwitcher({ hub, hubAddr, current, machines, onChange, onManage }: { + hub: string; hubAddr?: string; current: string | null; machines: MachineStatus[]; onChange: (name: string | null) => void; onManage: () => void }) { const [open, setOpen] = useState(false) const box = useRef(null) @@ -28,11 +30,11 @@ export default function MachineSwitcher({ hub, current, machines, onChange, onMa {open && (
{machines.map((m) => ( ))} diff --git a/web/src/Shell.tsx b/web/src/Shell.tsx index 0fa2efb..55f6ba8 100644 --- a/web/src/Shell.tsx +++ b/web/src/Shell.tsx @@ -210,7 +210,7 @@ export default function Shell({ me: hubMe, onLoggedOut }: { me: Me; onLoggedOut:
{ setView('machines'); setDrawer(false) }} />} + header={ { setView('machines'); setDrawer(false) }} />} onView={async (id) => { if (id !== view && !(await okToLeave())) return; setView(id as View); setDrawer(false) }} />
setDrawer(false)} /> diff --git a/web/src/api.ts b/web/src/api.ts index 10d6144..95f78f7 100644 --- a/web/src/api.ts +++ b/web/src/api.ts @@ -54,7 +54,7 @@ async function req(method: string, path: string, body?: unknown, local = fals return r.json() } -export interface Me { demo_url?: string; host: string; user: string; version: string; load: string; uptime: number; reboot_needed?: boolean; fingerprint?: string; arch?: string } +export interface Me { demo_url?: string; addr?: string; host: string; user: string; version: string; load: string; uptime: number; reboot_needed?: boolean; fingerprint?: string; arch?: string } export interface PushResult { name: string; ok: boolean; version?: string; error?: string } export interface MachineStatus { name: string; url: string; fingerprint?: string; added: string; online: boolean; host?: string; version?: string; load?: string; uptime?: number; reboot_needed?: boolean; last_seen?: string; error?: string } export interface Term { id: string; name: string; running: boolean; exit_code: number; created: string; clients: number }