Compare commits

...

1 Commits

Author SHA1 Message Date
Jiang Bohan
6d6a8c2ba5 refactor(cli): rename daemon status helper and align value column (MUL-2676)
- Rename printDaemonStatusTable -> printDaemonStatusReport. The helper
  emits a key/value list, not a table; the old name implied a tabular
  layout that never existed and made the call site read wrong.

- Align the value column dynamically off the widest key. Previously the
  spacing was hard-coded so the static rows (Version/Agents/Workspaces)
  all landed at column 14, but the dynamic "Daemon [profile]" label
  could outgrow that and push only its own value rightward, breaking
  vertical alignment as soon as a profile was active.

- Add negative coverage for cli_version absent / empty (the real
  back-compat contract for older daemons paired with a newer CLI) and a
  test that asserts the value column lines up under a long profile
  label.

Co-authored-by: multica-agent <github@multica.ai>
2026-05-26 15:31:00 +08:00
2 changed files with 109 additions and 7 deletions

View File

@@ -570,24 +570,40 @@ func runDaemonStatus(cmd *cobra.Command, _ []string) error {
return nil
}
printDaemonStatusTable(os.Stdout, label, health)
printDaemonStatusReport(os.Stdout, label, health)
return nil
}
func printDaemonStatusTable(w io.Writer, label string, health map[string]any) {
fmt.Fprintf(w, "%s: running (pid %v, uptime %v)\n", label, health["pid"], health["uptime"])
// printDaemonStatusReport renders a key/value summary of the daemon health
// response. The value column is aligned to the widest label so the dynamic
// "Daemon [profile]" row stays in step with the static rows below it.
func printDaemonStatusReport(w io.Writer, label string, health map[string]any) {
type row struct{ key, value string }
rows := []row{
{label, fmt.Sprintf("running (pid %v, uptime %v)", health["pid"], health["uptime"])},
}
if version, ok := health["cli_version"].(string); ok && version != "" {
fmt.Fprintf(w, "Version: %s\n", version)
rows = append(rows, row{"Version", version})
}
if agents, ok := health["agents"].([]any); ok && len(agents) > 0 {
parts := make([]string, len(agents))
for i, a := range agents {
parts[i] = fmt.Sprint(a)
}
fmt.Fprintf(w, "Agents: %s\n", strings.Join(parts, ", "))
rows = append(rows, row{"Agents", strings.Join(parts, ", ")})
}
if ws, ok := health["workspaces"].([]any); ok {
fmt.Fprintf(w, "Workspaces: %d\n", len(ws))
rows = append(rows, row{"Workspaces", strconv.Itoa(len(ws))})
}
keyWidth := 0
for _, r := range rows {
if n := len(r.key); n > keyWidth {
keyWidth = n
}
}
for _, r := range rows {
fmt.Fprintf(w, "%-*s %s\n", keyWidth+1, r.key+":", r.value)
}
}

View File

@@ -19,10 +19,96 @@ func TestPrintDaemonStatusIncludesCLIVersion(t *testing.T) {
}
var out bytes.Buffer
printDaemonStatusTable(&out, "Daemon", health)
printDaemonStatusReport(&out, "Daemon", health)
got := out.String()
if !strings.Contains(got, "Version: v9.9.9\n") {
t.Fatalf("daemon status output = %q, want CLI version line", got)
}
}
// TestPrintDaemonStatusOmitsVersionWhenMissing pins the back-compat contract:
// when the daemon doesn't report cli_version (older daemon paired with a newer
// CLI) or reports an empty string, the CLI must skip the line entirely instead
// of printing "Version: ".
func TestPrintDaemonStatusOmitsVersionWhenMissing(t *testing.T) {
t.Parallel()
cases := map[string]map[string]any{
"key missing": {
"status": "running",
"pid": float64(1234),
"uptime": "1h2m3s",
"workspaces": []any{},
},
"empty string": {
"status": "running",
"pid": float64(1234),
"uptime": "1h2m3s",
"cli_version": "",
"workspaces": []any{},
},
}
for name, health := range cases {
health := health
t.Run(name, func(t *testing.T) {
t.Parallel()
var out bytes.Buffer
printDaemonStatusReport(&out, "Daemon", health)
if strings.Contains(out.String(), "Version:") {
t.Fatalf("daemon status output = %q, want no Version line", out.String())
}
})
}
}
// TestPrintDaemonStatusAlignsValuesWithProfileLabel guards the alignment fix:
// before, a "Daemon [profile]" label was wider than the other keys, so the
// Daemon row's value started further right than every subsequent row. The
// report now pads every key to the widest one, so the value column lines up.
func TestPrintDaemonStatusAlignsValuesWithProfileLabel(t *testing.T) {
t.Parallel()
health := map[string]any{
"status": "running",
"pid": float64(1234),
"uptime": "1h2m3s",
"cli_version": "v9.9.9",
"agents": []any{"codex"},
"workspaces": []any{map[string]any{"id": "ws-1"}},
}
var out bytes.Buffer
printDaemonStatusReport(&out, "Daemon [staging]", health)
lines := strings.Split(strings.TrimRight(out.String(), "\n"), "\n")
if len(lines) < 2 {
t.Fatalf("expected multiple lines, got %q", out.String())
}
// Find the column where each row's value starts (first non-space after
// the colon). Every row must share the same column.
want := valueColumn(t, lines[0])
for _, line := range lines[1:] {
if got := valueColumn(t, line); got != want {
t.Fatalf("value column drift: line %q starts at col %d, want %d (first line: %q)",
line, got, want, lines[0])
}
}
}
func valueColumn(t *testing.T, line string) int {
t.Helper()
colon := strings.Index(line, ":")
if colon < 0 {
t.Fatalf("line missing colon: %q", line)
}
for i := colon + 1; i < len(line); i++ {
if line[i] != ' ' {
return i
}
}
t.Fatalf("line missing value: %q", line)
return 0
}