@@ -4,10 +4,21 @@ import (
44 "context"
55 "fmt"
66 "time"
7+
8+ "github.com/junhoyeo/contrabass/internal/types"
79)
810
9- // TeamEvent represents a team activity event
10- type TeamEvent struct {
11+ // EventFilter defines filters for querying events.
12+ type EventFilter struct {
13+ AfterEventID string
14+ Type string
15+ Worker string
16+ TaskID string
17+ WakeableOnly bool
18+ }
19+
20+ // cliEvent is the JSON shape returned by the team CLI event API.
21+ type cliEvent struct {
1122 EventID string `json:"event_id"`
1223 Team string `json:"team"`
1324 Type string `json:"type"`
@@ -21,25 +32,75 @@ type TeamEvent struct {
2132 CreatedAt time.Time `json:"created_at"`
2233}
2334
24- // EventFilter defines filters for querying events
25- type EventFilter struct {
26- AfterEventID string
27- Type string
28- Worker string
29- TaskID string
30- WakeableOnly bool
35+ func (e * cliEvent ) toTeamEvent () types.TeamEvent {
36+ data := make (map [string ]interface {})
37+ if e .Worker != "" {
38+ data ["worker" ] = e .Worker
39+ }
40+ if e .TaskID != "" {
41+ data ["task_id" ] = e .TaskID
42+ }
43+ if e .MessageID != "" {
44+ data ["message_id" ] = e .MessageID
45+ }
46+ if e .Reason != "" {
47+ data ["reason" ] = e .Reason
48+ }
49+ if e .State != "" {
50+ data ["state" ] = e .State
51+ }
52+ if e .PrevState != "" {
53+ data ["prev_state" ] = e .PrevState
54+ }
55+ if e .EventID != "" {
56+ data ["event_id" ] = e .EventID
57+ }
58+ for k , v := range e .Metadata {
59+ data [k ] = v
60+ }
61+ return types.TeamEvent {
62+ Type : e .Type ,
63+ TeamName : e .Team ,
64+ Data : data ,
65+ Timestamp : e .CreatedAt ,
66+ }
67+ }
68+
69+ func teamEventToCLI (teamName string , event * types.TeamEvent ) map [string ]interface {} {
70+ input := map [string ]interface {}{
71+ "team_name" : teamName ,
72+ "type" : event .Type ,
73+ }
74+ if w , ok := event .Data ["worker" ].(string ); ok && w != "" {
75+ input ["worker" ] = w
76+ }
77+ if t , ok := event .Data ["task_id" ].(string ); ok && t != "" {
78+ input ["task_id" ] = t
79+ }
80+ if m , ok := event .Data ["message_id" ].(string ); ok && m != "" {
81+ input ["message_id" ] = m
82+ }
83+ if r , ok := event .Data ["reason" ].(string ); ok && r != "" {
84+ input ["reason" ] = r
85+ }
86+ if s , ok := event .Data ["state" ].(string ); ok && s != "" {
87+ input ["state" ] = s
88+ }
89+ if p , ok := event .Data ["prev_state" ].(string ); ok && p != "" {
90+ input ["prev_state" ] = p
91+ }
92+ return input
3193}
3294
33- // ReadEvents retrieves events from the team event log
34- func (r * teamCLIRunner ) ReadEvents (ctx context.Context , workspace , teamName string , filter * EventFilter ) ([]TeamEvent , error ) {
95+ // ReadEvents retrieves events from the team event log.
96+ func (r * teamCLIRunner ) ReadEvents (ctx context.Context , workspace , teamName string , filter * EventFilter ) ([]types. TeamEvent , error ) {
3597 if filter == nil {
3698 filter = & EventFilter {}
3799 }
38100
39101 input := map [string ]interface {}{
40102 "team_name" : teamName ,
41103 }
42-
43104 if filter .AfterEventID != "" {
44105 input ["after_event_id" ] = filter .AfterEventID
45106 }
@@ -57,20 +118,24 @@ func (r *teamCLIRunner) ReadEvents(ctx context.Context, workspace, teamName stri
57118 }
58119
59120 var resp struct {
60- Count int `json:"count"`
61- Cursor string `json:"cursor"`
62- Events []TeamEvent `json:"events"`
121+ Count int `json:"count"`
122+ Cursor string `json:"cursor"`
123+ Events []cliEvent `json:"events"`
63124 }
64125
65126 if err := r .runTeamAPI (ctx , workspace , "read-events" , input , & resp ); err != nil {
66127 return nil , fmt .Errorf ("read team events: %w" , err )
67128 }
68129
69- return resp .Events , nil
130+ events := make ([]types.TeamEvent , len (resp .Events ))
131+ for i , e := range resp .Events {
132+ events [i ] = e .toTeamEvent ()
133+ }
134+ return events , nil
70135}
71136
72- // AwaitEvent waits for a specific event to occur
73- func (r * teamCLIRunner ) AwaitEvent (ctx context.Context , workspace , teamName string , filter * EventFilter , timeout time.Duration ) (* TeamEvent , error ) {
137+ // AwaitEvent waits for a specific event to occur.
138+ func (r * teamCLIRunner ) AwaitEvent (ctx context.Context , workspace , teamName string , filter * EventFilter , timeout time.Duration ) (* types. TeamEvent , error ) {
74139 if filter == nil {
75140 filter = & EventFilter {}
76141 }
@@ -79,7 +144,6 @@ func (r *teamCLIRunner) AwaitEvent(ctx context.Context, workspace, teamName stri
79144 "team_name" : teamName ,
80145 "timeout_ms" : timeout .Milliseconds (),
81146 }
82-
83147 if filter .AfterEventID != "" {
84148 input ["after_event_id" ] = filter .AfterEventID
85149 }
@@ -97,9 +161,9 @@ func (r *teamCLIRunner) AwaitEvent(ctx context.Context, workspace, teamName stri
97161 }
98162
99163 var resp struct {
100- Status string `json:"status"`
101- Cursor string `json:"cursor"`
102- Event * TeamEvent `json:"event"`
164+ Status string `json:"status"`
165+ Cursor string `json:"cursor"`
166+ Event * cliEvent `json:"event"`
103167 }
104168
105169 if err := r .runTeamAPI (ctx , workspace , "await-event" , input , & resp ); err != nil {
@@ -109,50 +173,31 @@ func (r *teamCLIRunner) AwaitEvent(ctx context.Context, workspace, teamName stri
109173 if resp .Status == "timeout" {
110174 return nil , fmt .Errorf ("timeout waiting for event" )
111175 }
112-
113176 if resp .Event == nil {
114177 return nil , fmt .Errorf ("no event received" )
115178 }
116179
117- return resp .Event , nil
180+ event := resp .Event .toTeamEvent ()
181+ return & event , nil
118182}
119183
120- // AppendEvent adds an event to the team event log
121- func (r * teamCLIRunner ) AppendEvent (ctx context.Context , workspace , teamName string , event * TeamEvent ) (* TeamEvent , error ) {
122- input := map [string ]interface {}{
123- "team_name" : teamName ,
124- "type" : event .Type ,
125- "worker" : event .Worker ,
126- }
127-
128- if event .TaskID != "" {
129- input ["task_id" ] = event .TaskID
130- }
131- if event .MessageID != "" {
132- input ["message_id" ] = event .MessageID
133- }
134- if event .Reason != "" {
135- input ["reason" ] = event .Reason
136- }
137- if event .State != "" {
138- input ["state" ] = event .State
139- }
140- if event .PrevState != "" {
141- input ["prev_state" ] = event .PrevState
142- }
184+ // AppendEvent adds an event to the team event log.
185+ func (r * teamCLIRunner ) AppendEvent (ctx context.Context , workspace , teamName string , event * types.TeamEvent ) (* types.TeamEvent , error ) {
186+ input := teamEventToCLI (teamName , event )
143187
144188 var resp struct {
145- Event TeamEvent `json:"event"`
189+ Event cliEvent `json:"event"`
146190 }
147191
148192 if err := r .runTeamAPI (ctx , workspace , "append-event" , input , & resp ); err != nil {
149193 return nil , fmt .Errorf ("append team event: %w" , err )
150194 }
151195
152- return & resp .Event , nil
196+ result := resp .Event .toTeamEvent ()
197+ return & result , nil
153198}
154199
155- // IdleState represents the idle state of the team
200+ // IdleState represents the idle state of the team.
156201type IdleState struct {
157202 TeamName string `json:"team_name"`
158203 WorkerCount int `json:"worker_count"`
@@ -167,20 +212,18 @@ type IdleState struct {
167212 } `json:"last_all_workers_idle_event,omitempty"`
168213}
169214
170- // ReadIdleState retrieves the current idle state of the team
215+ // ReadIdleState retrieves the current idle state of the team.
171216func (r * teamCLIRunner ) ReadIdleState (ctx context.Context , workspace , teamName string ) (* IdleState , error ) {
172217 var state IdleState
173-
174218 if err := r .runTeamAPI (ctx , workspace , "read-idle-state" , map [string ]string {
175219 "team_name" : teamName ,
176220 }, & state ); err != nil {
177221 return nil , fmt .Errorf ("read idle state: %w" , err )
178222 }
179-
180223 return & state , nil
181224}
182225
183- // StallState represents whether the team is stalled
226+ // StallState represents whether the team is stalled.
184227type StallState struct {
185228 TeamName string `json:"team_name"`
186229 TeamStalled bool `json:"team_stalled"`
@@ -193,15 +236,13 @@ type StallState struct {
193236 Reasons []string `json:"reasons"`
194237}
195238
196- // ReadStallState retrieves the current stall state of the team
239+ // ReadStallState retrieves the current stall state of the team.
197240func (r * teamCLIRunner ) ReadStallState (ctx context.Context , workspace , teamName string ) (* StallState , error ) {
198241 var state StallState
199-
200242 if err := r .runTeamAPI (ctx , workspace , "read-stall-state" , map [string ]string {
201243 "team_name" : teamName ,
202244 }, & state ); err != nil {
203245 return nil , fmt .Errorf ("read stall state: %w" , err )
204246 }
205-
206247 return & state , nil
207248}
0 commit comments