@@ -3,9 +3,10 @@ package cli
33import (
44 "fmt"
55 "io"
6+ "strconv"
67 "strings"
78
8- flashduty "github.com/flashcatcloud/flashduty-sdk "
9+ "github.com/flashcatcloud/go-flashduty "
910 "github.com/spf13/cobra"
1011
1112 "github.com/flashcatcloud/flashduty-cli/internal/output"
@@ -26,7 +27,7 @@ func newAlertCmd() *cobra.Command {
2627}
2728
2829func newAlertListCmd () * cobra.Command {
29- var severity , channel , title , since , until string
30+ var severity , channel , since , until string
3031 var active , recovered , muted bool
3132 var limit , page int
3233
@@ -48,49 +49,50 @@ func newAlertListCmd() *cobra.Command {
4849 return fmt .Errorf ("invalid --until: %w" , err )
4950 }
5051
51- input := & flashduty.ListAlertsInput {
52+ req := & flashduty.AlertListRequest {
5253 StartTime : startTime ,
5354 EndTime : endTime ,
5455 AlertSeverity : severity ,
55- Title : title ,
56- Limit : limit ,
57- Page : page ,
5856 }
57+ req .Limit = limit
58+ req .Page = page
5959
60+ // Preserve legacy semantics: --active sends is_active=true,
61+ // --recovered sends is_active=false, neither omits the filter.
6062 if active {
61- input .IsActive = boolPtr (true )
63+ req .IsActive = flashduty . Bool (true )
6264 } else if recovered {
63- input .IsActive = boolPtr (false )
65+ req .IsActive = flashduty . Bool (false )
6466 }
6567
6668 if muted {
67- input .EverMuted = boolPtr (true )
69+ req .EverMuted = flashduty . Bool (true )
6870 }
6971
7072 if channel != "" {
7173 channelIDs , err := parseIntSlice (channel )
7274 if err != nil {
7375 return fmt .Errorf ("invalid --channel: %w" , err )
7476 }
75- input .ChannelIDs = channelIDs
77+ req .ChannelIDs = channelIDs
7678 }
7779
78- result , err := ctx .Client .ListAlerts (cmdContext (ctx .Cmd ), input )
80+ result , _ , err := ctx .Client .Alerts . ReadList (cmdContext (ctx .Cmd ), req )
7981 if err != nil {
8082 return err
8183 }
8284
8385 cols := []output.Column {
84- {Header : "ID" , Field : func (v any ) string { return v .(flashduty.Alert ).AlertID }},
85- {Header : "TITLE" , MaxWidth : 50 , Field : func (v any ) string { return v .(flashduty.Alert ).Title }},
86- {Header : "SEVERITY" , Field : func (v any ) string { return v .(flashduty.Alert ).AlertSeverity }},
87- {Header : "STATUS" , Field : func (v any ) string { return v .(flashduty.Alert ).AlertStatus }},
88- {Header : "EVENTS" , Field : func (v any ) string { return fmt .Sprintf ("%d" , v .(flashduty.Alert ).EventCnt ) }},
89- {Header : "CHANNEL" , Field : func (v any ) string { return v .(flashduty.Alert ).ChannelName }},
90- {Header : "STARTED" , Field : func (v any ) string { return output .FormatTime (v .(flashduty.Alert ).StartTime ) }},
86+ {Header : "ID" , Field : func (v any ) string { return v .(flashduty.AlertItem ).AlertID }},
87+ {Header : "TITLE" , MaxWidth : 50 , Field : func (v any ) string { return v .(flashduty.AlertItem ).Title }},
88+ {Header : "SEVERITY" , Field : func (v any ) string { return v .(flashduty.AlertItem ).AlertSeverity }},
89+ {Header : "STATUS" , Field : func (v any ) string { return v .(flashduty.AlertItem ).AlertStatus }},
90+ {Header : "EVENTS" , Field : func (v any ) string { return fmt .Sprintf ("%d" , v .(flashduty.AlertItem ).EventCnt ) }},
91+ {Header : "CHANNEL" , Field : func (v any ) string { return v .(flashduty.AlertItem ).ChannelName }},
92+ {Header : "STARTED" , Field : func (v any ) string { return output .FormatTime (v .(flashduty.AlertItem ).StartTime ) }},
9193 }
9294
93- return ctx .PrintList (result .Alerts , cols , len (result .Alerts ), page , result .Total )
95+ return ctx .PrintList (result .Items , cols , len (result .Items ), page , int ( result .Total ) )
9496 })
9597 },
9698 }
@@ -100,7 +102,6 @@ func newAlertListCmd() *cobra.Command {
100102 cmd .Flags ().BoolVar (& recovered , "recovered" , false , "Show recovered only" )
101103 cmd .Flags ().StringVar (& channel , "channel" , "" , "Comma-separated channel IDs" )
102104 cmd .Flags ().BoolVar (& muted , "muted" , false , "Show ever-muted only" )
103- cmd .Flags ().StringVar (& title , "title" , "" , "Search by title keyword" )
104105 cmd .Flags ().StringVar (& since , "since" , "24h" , "Start time" )
105106 cmd .Flags ().StringVar (& until , "until" , "now" , "End time" )
106107 cmd .Flags ().IntVar (& limit , "limit" , 20 , "Max results" )
@@ -116,32 +117,36 @@ func newAlertGetCmd() *cobra.Command {
116117 Args : requireArgs ("alert_id" ),
117118 RunE : func (cmd * cobra.Command , args []string ) error {
118119 return runCommand (cmd , args , func (ctx * RunContext ) error {
119- result , err := ctx .Client .GetAlertDetail (cmdContext (ctx .Cmd ), & flashduty.GetAlertDetailInput {
120+ result , _ , err := ctx .Client .Alerts . ReadInfo (cmdContext (ctx .Cmd ), & flashduty.AlertInfoRequest {
120121 AlertID : ctx .Args [0 ],
121122 })
122123 if err != nil {
123124 return err
124125 }
125126
126127 if ctx .Structured () {
127- return ctx .Printer .Print (result . Alert , nil )
128+ return ctx .Printer .Print (result , nil )
128129 }
129130
130- printAlertDetail (ctx .Writer , result . Alert )
131+ printAlertDetail (ctx .Writer , result )
131132 return nil
132133 })
133134 },
134135 }
135136}
136137
137- func printAlertDetail (w io.Writer , a flashduty.Alert ) {
138+ func printAlertDetail (w io.Writer , a * flashduty.AlertItem ) {
139+ if a == nil {
140+ return
141+ }
142+
138143 labels := make ([]string , 0 , len (a .Labels ))
139144 for k , v := range a .Labels {
140145 labels = append (labels , k + "=" + v )
141146 }
142147
143148 incidentInfo := "-"
144- if a .Incident != nil {
149+ if a .Incident . IncidentID != "" {
145150 incidentInfo = fmt .Sprintf ("%s (%s)" , a .Incident .IncidentID , a .Incident .Progress )
146151 }
147152
@@ -174,27 +179,27 @@ func newAlertEventsCmd() *cobra.Command {
174179 Args : requireArgs ("alert_id" ),
175180 RunE : func (cmd * cobra.Command , args []string ) error {
176181 return runCommand (cmd , args , func (ctx * RunContext ) error {
177- result , err := ctx .Client .ListAlertEvents (cmdContext (ctx .Cmd ), & flashduty.ListAlertEventsInput {
182+ result , _ , err := ctx .Client .Alerts . ReadEventList (cmdContext (ctx .Cmd ), & flashduty.AlertEventListRequest {
178183 AlertID : ctx .Args [0 ],
179184 })
180185 if err != nil {
181186 return err
182187 }
183188
184- if len (result .AlertEvents ) == 0 {
189+ if len (result .Items ) == 0 {
185190 ctx .WriteResult ("No alert events found." )
186191 return nil
187192 }
188193
189194 cols := []output.Column {
190- {Header : "EVENT_ID" , Field : func (v any ) string { return v .(flashduty.AlertEvent ).EventID }},
191- {Header : "SEVERITY" , Field : func (v any ) string { return v .(flashduty.AlertEvent ).EventSeverity }},
192- {Header : "STATUS" , Field : func (v any ) string { return v .(flashduty.AlertEvent ).EventStatus }},
193- {Header : "TIME" , Field : func (v any ) string { return output .FormatTime (v .(flashduty.AlertEvent ).EventTime ) }},
194- {Header : "TITLE" , MaxWidth : 50 , Field : func (v any ) string { return v .(flashduty.AlertEvent ).Title }},
195+ {Header : "EVENT_ID" , Field : func (v any ) string { return v .(flashduty.AlertEventItem ).EventID }},
196+ {Header : "SEVERITY" , Field : func (v any ) string { return v .(flashduty.AlertEventItem ).EventSeverity }},
197+ {Header : "STATUS" , Field : func (v any ) string { return v .(flashduty.AlertEventItem ).EventStatus }},
198+ {Header : "TIME" , Field : func (v any ) string { return output .FormatTime (v .(flashduty.AlertEventItem ).EventTime ) }},
199+ {Header : "TITLE" , MaxWidth : 50 , Field : func (v any ) string { return v .(flashduty.AlertEventItem ).Title }},
195200 }
196201
197- return ctx .PrintTotal (result .AlertEvents , cols , len (result .AlertEvents ))
202+ return ctx .PrintTotal (result .Items , cols , len (result .Items ))
198203 })
199204 },
200205 }
@@ -209,11 +214,11 @@ func newAlertTimelineCmd() *cobra.Command {
209214 Args : requireArgs ("alert_id" ),
210215 RunE : func (cmd * cobra.Command , args []string ) error {
211216 return runCommand (cmd , args , func (ctx * RunContext ) error {
212- result , err := ctx . Client . GetAlertFeed ( cmdContext ( ctx . Cmd ), & flashduty.GetAlertFeedInput {
213- AlertID : ctx . Args [ 0 ],
214- Limit : limit ,
215- Page : page ,
216- } )
217+ req := & flashduty.AlertFeedRequest { AlertID : ctx . Args [ 0 ]}
218+ req . Limit = limit
219+ req . Page = page
220+
221+ result , _ , err := ctx . Client . Alerts . ReadFeed ( cmdContext ( ctx . Cmd ), req )
217222 if err != nil {
218223 return err
219224 }
@@ -223,12 +228,28 @@ func newAlertTimelineCmd() *cobra.Command {
223228 return nil
224229 }
225230
231+ // go-flashduty returns raw feed items, so replicate the legacy
232+ // SDK's operator-name enrichment by resolving each entry's actor
233+ // (creator) person ID via /person/infos. Best-effort: the
234+ // OPERATOR column falls back to the numeric ID when a name can't
235+ // be resolved.
236+ nameByID := resolveAlertFeedOperators (ctx , result .Items )
237+
226238 cols := []output.Column {
227- {Header : "TIME" , Field : func (v any ) string { return output .FormatTime (v .(flashduty.TimelineEvent ).Timestamp ) }},
228- {Header : "TYPE" , Field : func (v any ) string { return v .(flashduty.TimelineEvent ).Type }},
229- {Header : "OPERATOR" , Field : func (v any ) string { return v .(flashduty.TimelineEvent ).OperatorName }},
239+ {Header : "TIME" , Field : func (v any ) string { return output .FormatTime (v .(flashduty.FeedItem ).CreatedAt ) }},
240+ {Header : "TYPE" , Field : func (v any ) string { return string (v .(flashduty.FeedItem ).Type ) }},
241+ {Header : "OPERATOR" , Field : func (v any ) string {
242+ it := v .(flashduty.FeedItem )
243+ if it .CreatorID == 0 {
244+ return "system"
245+ }
246+ if n , ok := nameByID [it .CreatorID ]; ok && n != "" {
247+ return n
248+ }
249+ return strconv .FormatInt (it .CreatorID , 10 )
250+ }},
230251 {Header : "DETAIL" , MaxWidth : 80 , Field : func (v any ) string {
231- d := v .(flashduty.TimelineEvent ).Detail
252+ d := v .(flashduty.FeedItem ).Detail
232253 if d == nil {
233254 return "-"
234255 }
@@ -247,6 +268,37 @@ func newAlertTimelineCmd() *cobra.Command {
247268 return cmd
248269}
249270
271+ // resolveAlertFeedOperators resolves the actor (creator) person IDs of
272+ // alert-feed items to display names via /person/infos, replicating the
273+ // operator-name enrichment the legacy SDK did server-side. Best-effort: a
274+ // lookup failure yields a nil map and callers fall back to the numeric ID.
275+ func resolveAlertFeedOperators (rc * RunContext , items []flashduty.FeedItem ) map [int64 ]string {
276+ seen := make (map [int64 ]struct {}, len (items ))
277+ ids := make ([]uint64 , 0 , len (items ))
278+ for _ , it := range items {
279+ if it .CreatorID == 0 {
280+ continue
281+ }
282+ if _ , ok := seen [it .CreatorID ]; ok {
283+ continue
284+ }
285+ seen [it .CreatorID ] = struct {}{}
286+ ids = append (ids , uint64 (it .CreatorID ))
287+ }
288+ if len (ids ) == 0 {
289+ return nil
290+ }
291+ resp , _ , err := rc .Client .Members .PersonInfos (cmdContext (rc .Cmd ), & flashduty.PersonInfosRequest {PersonIDs : ids })
292+ if err != nil || resp == nil {
293+ return nil
294+ }
295+ out := make (map [int64 ]string , len (resp .Items ))
296+ for _ , p := range resp .Items {
297+ out [int64 (p .PersonID )] = p .PersonName
298+ }
299+ return out
300+ }
301+
250302func newAlertMergeCmd () * cobra.Command {
251303 var incidentID , comment string
252304
@@ -256,7 +308,7 @@ func newAlertMergeCmd() *cobra.Command {
256308 Args : requireArgs ("alert_id" ),
257309 RunE : func (cmd * cobra.Command , args []string ) error {
258310 return runCommand (cmd , args , func (ctx * RunContext ) error {
259- if err := ctx .Client .MergeAlertsToIncident (cmdContext (ctx .Cmd ), & flashduty.MergeAlertsInput {
311+ if _ , err := ctx .Client .Alerts . WriteMerge (cmdContext (ctx .Cmd ), & flashduty.AlertMergeRequest {
260312 AlertIDs : ctx .Args ,
261313 IncidentID : incidentID ,
262314 Comment : comment ,
0 commit comments