agent-orchestrator/backend/internal/cli/agent.go

111 lines
2.8 KiB
Go

package cli
import (
"fmt"
"sort"
"text/tabwriter"
"github.com/spf13/cobra"
)
type agentListOptions struct {
refresh bool
json bool
}
// agentInfo mirrors the daemon's agent Info body for the CLI client.
type agentInfo struct {
ID string `json:"id"`
Label string `json:"label"`
AuthStatus string `json:"authStatus,omitempty"`
}
// agentInventory mirrors GET /api/v1/agents and POST /api/v1/agents/refresh.
type agentInventory struct {
Supported []agentInfo `json:"supported"`
Installed []agentInfo `json:"installed"`
Authorized []agentInfo `json:"authorized"`
}
func newAgentCommand(ctx *commandContext) *cobra.Command {
cmd := &cobra.Command{
Use: "agent",
Short: "Inspect agent catalog readiness",
}
cmd.AddCommand(newAgentListCommand(ctx))
return cmd
}
func newAgentListCommand(ctx *commandContext) *cobra.Command {
var opts agentListOptions
cmd := &cobra.Command{
Use: "ls",
Aliases: []string{"list"},
Short: "List supported agents and local auth readiness",
Args: noArgs,
RunE: func(cmd *cobra.Command, args []string) error {
inv, err := ctx.fetchAgentInventory(cmd.Context(), opts.refresh)
if err != nil {
return err
}
if opts.json {
return writeJSON(cmd.OutOrStdout(), inv)
}
return writeAgentList(cmd, inv)
},
}
cmd.Flags().BoolVar(&opts.refresh, "refresh", false, "Refresh local install/auth probes before listing")
cmd.Flags().BoolVar(&opts.json, "json", false, "Output raw agent catalog JSON")
return cmd
}
func writeAgentList(cmd *cobra.Command, inv agentInventory) error {
out := cmd.OutOrStdout()
if len(inv.Supported) == 0 {
_, err := fmt.Fprintln(out, "No agents supported by this daemon.")
return err
}
sort.Slice(inv.Supported, func(i, j int) bool {
return inv.Supported[i].ID < inv.Supported[j].ID
})
installed := agentInfoByID(inv.Installed)
authorized := agentInfoByID(inv.Authorized)
tw := tabwriter.NewWriter(out, 0, 4, 2, ' ', 0)
if _, err := fmt.Fprintln(tw, "ID\tLABEL\tINSTALL\tAUTH"); err != nil {
return err
}
for _, info := range inv.Supported {
installLabel := "needs install"
authLabel := "auth unknown"
if installedInfo, ok := installed[info.ID]; ok {
installLabel = "installed"
switch installedInfo.AuthStatus {
case "authorized":
authLabel = "authorized"
case "unauthorized":
authLabel = "needs auth"
default:
authLabel = "auth unknown"
}
}
if _, ok := authorized[info.ID]; ok {
installLabel = "installed"
authLabel = "authorized"
}
if _, err := fmt.Fprintf(tw, "%s\t%s\t%s\t%s\n", info.ID, info.Label, installLabel, authLabel); err != nil {
return err
}
}
return tw.Flush()
}
func agentInfoByID(infos []agentInfo) map[string]agentInfo {
out := make(map[string]agentInfo, len(infos))
for _, info := range infos {
out[info.ID] = info
}
return out
}