@@ -118,6 +118,18 @@ func (v *VLLMAdapter) getHashAsUint64(raw any) (uint64, error) {
118118 }
119119}
120120
121+ const (
122+ // Expected field counts for msgpack array structs.
123+ // Used for padding shorter arrays from SGLang which may omit trailing optional fields.
124+ // See SGLang source: sglang/srt/disaggregation/kv_events.py (BlockStored, BlockRemoved classes)
125+ blockStoredFieldCount = 9 // tag + block_hashes + parent + tokens + block_size + lora_id + medium + lora_name + extra_keys
126+ blockRemovedFieldCount = 3 // tag + block_hashes + medium
127+
128+ // Minimum required fields (excluding trailing optional ones).
129+ blockStoredMinFields = 5 // tag + block_hashes + parent + tokens + block_size
130+ blockRemovedMinFields = 2 // tag + block_hashes
131+ )
132+
121133// vLLM msgpack-specific event structures.
122134// These structs are designed for msgpack array encoding and match vLLM's format.
123135type msgpackVLLMEventBatch struct {
@@ -188,10 +200,31 @@ func (v *VLLMAdapter) decodeVLLMEvent(rawEventBytes []byte) (kvevents.GenericEve
188200 return converter (rawEventBytes )
189201}
190202
191- // convertBlockStoredEvent decodes and converts a msgpack vLLM BlockStored event to a generic event.
203+ // convertBlockStoredEvent decodes and converts a BlockStored event to a generic event.
204+ // Supports both vLLM and SGLang by padding shorter arrays with nil for trailing optional fields.
205+ // SGLang may omit medium, lora_name, and extra_keys when they are None/default.
206+ // See: sglang/srt/disaggregation/kv_events.py (BlockStored class, array_like=True, omit_defaults=True)
192207func (v * VLLMAdapter ) convertBlockStoredEvent (rawEventBytes []byte ) (kvevents.GenericEvent , error ) {
208+ var fields []any
209+ if err := msgpack .Unmarshal (rawEventBytes , & fields ); err != nil {
210+ return nil , fmt .Errorf ("failed to decode BlockStored event: %w" , err )
211+ }
212+
213+ if len (fields ) < blockStoredMinFields {
214+ return nil , fmt .Errorf ("BlockStored event has too few fields: %d (minimum %d)" , len (fields ), blockStoredMinFields )
215+ }
216+
217+ // Pad to full struct size so msgpack array decode succeeds.
218+ for len (fields ) < blockStoredFieldCount {
219+ fields = append (fields , nil )
220+ }
221+ paddedBytes , err := msgpack .Marshal (fields )
222+ if err != nil {
223+ return nil , fmt .Errorf ("failed to re-marshal padded BlockStored event: %w" , err )
224+ }
225+
193226 var vllmEvent msgpackVLLMBlockStoredEvent
194- if err := msgpack .Unmarshal (rawEventBytes , & vllmEvent ); err != nil {
227+ if err := msgpack .Unmarshal (paddedBytes , & vllmEvent ); err != nil {
195228 return nil , fmt .Errorf ("failed to decode BlockStored event: %w" , err )
196229 }
197230
@@ -244,10 +277,29 @@ func (v *VLLMAdapter) convertBlockStoredEvent(rawEventBytes []byte) (kvevents.Ge
244277 }, nil
245278}
246279
247- // convertBlockRemovedEvent decodes and converts a msgpack vLLM BlockRemoved event to a generic event.
280+ // convertBlockRemovedEvent decodes and converts a BlockRemoved event to a generic event.
281+ // Supports both vLLM and SGLang by padding shorter arrays with nil for trailing optional fields.
282+ // See: sglang/srt/disaggregation/kv_events.py (BlockRemoved class, array_like=True, omit_defaults=True)
248283func (v * VLLMAdapter ) convertBlockRemovedEvent (rawEventBytes []byte ) (kvevents.GenericEvent , error ) {
284+ var fields []any
285+ if err := msgpack .Unmarshal (rawEventBytes , & fields ); err != nil {
286+ return nil , fmt .Errorf ("failed to decode BlockRemoved event: %w" , err )
287+ }
288+
289+ if len (fields ) < blockRemovedMinFields {
290+ return nil , fmt .Errorf ("BlockRemoved event has too few fields: %d (minimum %d)" , len (fields ), blockRemovedMinFields )
291+ }
292+
293+ for len (fields ) < blockRemovedFieldCount {
294+ fields = append (fields , nil )
295+ }
296+ paddedBytes , err := msgpack .Marshal (fields )
297+ if err != nil {
298+ return nil , fmt .Errorf ("failed to re-marshal padded BlockRemoved event: %w" , err )
299+ }
300+
249301 var vllmEvent msgpackVLLMBlockRemovedEvent
250- if err := msgpack .Unmarshal (rawEventBytes , & vllmEvent ); err != nil {
302+ if err := msgpack .Unmarshal (paddedBytes , & vllmEvent ); err != nil {
251303 return nil , fmt .Errorf ("failed to decode BlockRemoved event: %w" , err )
252304 }
253305
0 commit comments