@@ -37,8 +37,11 @@ type RegistrationState struct {
3737 StatusCode int `json:"status_code,omitempty"`
3838 RemoteSessionID string `json:"remote_session_id,omitempty"`
3939 RegistrationID string `json:"registration_id,omitempty"`
40+ ProtocolVersion string `json:"protocol_version,omitempty"`
41+ Capabilities []string `json:"capabilities,omitempty"`
4042 WebSocketURL string `json:"websocket_url,omitempty"`
4143 PollURL string `json:"poll_url,omitempty"`
44+ LeaseRenewURL string `json:"lease_renew_url,omitempty"`
4245 Message string `json:"message,omitempty"`
4346 Error string `json:"error,omitempty"`
4447 ManifestServices int `json:"manifest_services,omitempty"`
@@ -198,12 +201,24 @@ func applyRegistrationResponseFields(state *RegistrationState, raw map[string]an
198201 if state .RegistrationID == "" {
199202 state .RegistrationID = firstString (raw , "registration_id" , "registrationId" , "id" )
200203 }
204+ if state .ProtocolVersion == "" {
205+ state .ProtocolVersion = firstString (raw , "protocol_version" , "protocolVersion" , "remote_protocol_version" , "remoteProtocolVersion" , "version" )
206+ }
207+ if len (state .Capabilities ) == 0 {
208+ state .Capabilities = firstStringList (raw , "capabilities" , "features" , "supported_capabilities" , "supportedCapabilities" )
209+ }
201210 if state .WebSocketURL == "" {
202211 state .WebSocketURL = firstString (raw , "websocket_url" , "websocketUrl" , "web_socket_url" , "ws_url" , "wsUrl" )
203212 }
204213 if state .PollURL == "" {
205214 state .PollURL = firstString (raw , "poll_url" , "pollUrl" , "events_url" , "eventsUrl" )
206215 }
216+ if state .LeaseRenewURL == "" {
217+ state .LeaseRenewURL = firstString (raw , "lease_renew_url" , "leaseRenewUrl" , "lease_refresh_url" , "leaseRefreshUrl" , "renew_url" , "renewUrl" )
218+ }
219+ if state .LeaseRenewURL == "" {
220+ state .LeaseRenewURL = stringFromNestedMap (raw ["lease" ], "renew_url" , "renewUrl" , "refresh_url" , "refreshUrl" , "url" )
221+ }
207222 if state .Message == "" {
208223 state .Message = firstString (raw , "message" , "status" , "detail" )
209224 }
@@ -231,6 +246,59 @@ func firstString(values map[string]any, keys ...string) string {
231246 return ""
232247}
233248
249+ func firstStringList (values map [string ]any , keys ... string ) []string {
250+ for _ , key := range keys {
251+ if value , ok := values [key ]; ok {
252+ if list := normalizeStringList (value ); len (list ) > 0 {
253+ return list
254+ }
255+ }
256+ }
257+ return nil
258+ }
259+
260+ func normalizeStringList (value any ) []string {
261+ switch typed := value .(type ) {
262+ case []string :
263+ return cleanStringList (typed )
264+ case []any :
265+ items := make ([]string , 0 , len (typed ))
266+ for _ , item := range typed {
267+ items = append (items , fmt .Sprint (item ))
268+ }
269+ return cleanStringList (items )
270+ case string :
271+ text := strings .TrimSpace (typed )
272+ if text == "" {
273+ return nil
274+ }
275+ if strings .Contains (text , "," ) {
276+ return cleanStringList (strings .Split (text , "," ))
277+ }
278+ return cleanStringList (strings .Fields (text ))
279+ default :
280+ text := strings .TrimSpace (fmt .Sprint (typed ))
281+ if text == "" || text == "<nil>" {
282+ return nil
283+ }
284+ return []string {text }
285+ }
286+ }
287+
288+ func cleanStringList (values []string ) []string {
289+ cleaned := make ([]string , 0 , len (values ))
290+ seen := make (map [string ]bool , len (values ))
291+ for _ , value := range values {
292+ text := strings .TrimSpace (value )
293+ if text == "" || text == "<nil>" || seen [text ] {
294+ continue
295+ }
296+ seen [text ] = true
297+ cleaned = append (cleaned , text )
298+ }
299+ return cleaned
300+ }
301+
234302func remoteRegistrationError (status string , body []byte ) string {
235303 bodyText := strings .TrimSpace (string (body ))
236304 if bodyText == "" {
0 commit comments