feat(agent+panel): sing-box core version probe and display (round-2 #4)

agent-go: engineReport gains singBoxVersion. The probe runs
`sing-box version` once, parses the version token from its first line
('unknown' from unstamped builds reports empty), and caches it keyed by
the binary's mtime+size — re-probed only when an engine install/update
replaces the file. Steady-state heartbeats pay one stat, no subprocess.
Agent version stays 0.6.8.

panel-go: EngineState.singBoxVersion persisted from heartbeats (old
agents without the field keep showing '-'), servers table core-version
column now renders it. Golden gains heartbeatWithEngine +
serversAfterEngineHeartbeat sections locking the full chain, plus a
listen-address (<hostip>) normalization for the sandbox bind address.
singboxversion_test.go covers parsing, cache hits, and re-probe on
binary replacement.
This commit is contained in:
aaaamoooo
2026-10-21 11:18:00 +08:00
parent 35c9bd2cc0
commit b49c134513
7 changed files with 248 additions and 23 deletions
+1 -1
View File
@@ -476,7 +476,7 @@ function renderServers() {
<td><span class="num">${cpuPct == null ? '—' : `${cpuPct.toFixed(1)}%`}</span></td>
<td><span class="num">${memPct == null ? '—' : `${memPct.toFixed(1)}%`}</span></td>
<td><span class="ver-cell"><span class="ver">${esc(server.agentVersion || '—')}</span>${server.agentVersion && versionLessThan(server.agentVersion, state.version) ? '<span class="badge orange">有可用更新</span>' : ''}</span></td>
<td><span class="ver">—</span></td>
<td><span class="ver">${esc(server.engine && server.engine.singBoxVersion ? server.engine.singBoxVersion : '—')}</span></td>
<td><span class="num">${system.uptimeSeconds ? fmtUptime(system.uptimeSeconds) : '—'}</span></td>
<td><span class="clients-cell">${ICONS.users}${clients.total}<span class="on-n">${clients.online}</span></span></td>
<td><span class="hb">${server.lastSeenAt ? relTime(server.lastSeenAt) : '等待注册'}</span></td></tr>`;