@@ -17,6 +17,7 @@ type lsOptions struct {
1717 all bool
1818 node string
1919 live bool
20+ entrypoints bool
2021 outputFormat string
2122 stdout io.Writer
2223 stdoutTTY bool
@@ -29,10 +30,12 @@ type reasonerListResponse struct {
2930}
3031
3132type reasonerListItem struct {
32- Node string `json:"node"`
33- Reasoner string `json:"reasoner"`
34- LastRunAt * string `json:"last_run_at,omitempty"`
35- Status string `json:"status"`
33+ Node string `json:"node"`
34+ Reasoner string `json:"reasoner"`
35+ Description string `json:"description,omitempty"`
36+ Tags []string `json:"tags,omitempty"`
37+ LastRunAt * string `json:"last_run_at,omitempty"`
38+ Status string `json:"status"`
3639}
3740
3841func NewReasonerListCommand () * cobra.Command {
@@ -57,6 +60,7 @@ func NewReasonerListCommand() *cobra.Command {
5760 cmd .Flags ().BoolVar (& opts .all , "all" , false , "Show every reasoner" )
5861 cmd .Flags ().StringVar (& opts .node , "node" , "" , "Filter to a single node" )
5962 cmd .Flags ().BoolVar (& opts .live , "live" , false , "Only show reasoners whose node is live" )
63+ cmd .Flags ().BoolVarP (& opts .entrypoints , "entrypoints" , "e" , false , "Only show reasoners tagged as entry points" )
6064 cmd .Flags ().StringVarP (& opts .outputFormat , "output" , "o" , "" , "Output format: pretty, json, yaml" )
6165 return cmd
6266}
@@ -82,6 +86,9 @@ func runReasonerList(ctx context.Context, query string, opts *lsOptions) error {
8286 if opts .live {
8387 values .Set ("live" , "true" )
8488 }
89+ if opts .entrypoints {
90+ values .Set ("entrypoints" , "true" )
91+ }
8592 resp , err := makeRequest (ctx , http .MethodGet , appendQuery ("/api/v1/reasoners" , values ), nil , "application/json" )
8693 if err != nil {
8794 return cliExitError {Code : 3 , Err : err }
@@ -107,13 +114,39 @@ func renderReasonerList(out io.Writer, resp reasonerListResponse, recentHeader b
107114 }
108115 for _ , item := range resp .Reasoners {
109116 name := item .Node + "." + item .Reasoner
110- fmt .Fprintf (out , "%-28s %-12s %s\n " , name , relativeTime (item .LastRunAt ), item .Status )
117+ fmt .Fprintf (out , "%-28s %-12s %-6s % s\n " , name , relativeTime (item .LastRunAt ), item .Status , describeReasoner ( item ) )
111118 }
112119 if resp .Total > resp .Shown {
113120 fmt .Fprintf (out , "\n %d more recent - %d total - use `af ls --all`\n " , resp .Total - resp .Shown , resp .Total )
114121 }
115122}
116123
124+ // describeReasoner renders the trailing description column: entry points are
125+ // labeled so callers can spot a node's intended surface, and long descriptions
126+ // are truncated to keep rows on one line.
127+ func describeReasoner (item reasonerListItem ) string {
128+ const maxLen = 80
129+ desc := strings .Join (strings .Fields (item .Description ), " " )
130+ if len (desc ) > maxLen {
131+ desc = desc [:maxLen - 1 ] + "…"
132+ }
133+ entry := false
134+ for _ , tag := range item .Tags {
135+ if strings .EqualFold (strings .TrimSpace (tag ), "entrypoint" ) {
136+ entry = true
137+ break
138+ }
139+ }
140+ switch {
141+ case entry && desc != "" :
142+ return "[entrypoint] " + desc
143+ case entry :
144+ return "[entrypoint]"
145+ default :
146+ return desc
147+ }
148+ }
149+
117150func relativeTime (value * string ) string {
118151 if value == nil || strings .TrimSpace (* value ) == "" {
119152 return "-"
0 commit comments