@@ -214,6 +214,10 @@ interface RawOperation {
214214 * Transform the raw operations list response into `Operation[]`.
215215 *
216216 * Extracts `kind`, `path`, and `type` from the `x-medkit` vendor extension.
217+ *
218+ * NOTE: currently only reads `x-medkit.ros2.*`. Extending the generic
219+ * middleware fallback here (parity with `transformDataResponse`) is tracked
220+ * separately.
217221 */
218222export function transformOperationsResponse ( rawData : unknown ) : Operation [ ] {
219223 if ( ! rawData || typeof rawData !== 'object' ) return [ ] ;
@@ -275,12 +279,27 @@ export function transformOperationsResponse(rawData: unknown): Operation[] {
275279
276280/**
277281 * Raw data item shape from the gateway data endpoint.
282+ *
283+ * Fields under `x-medkit` are generic SOVD vendor extensions. Gateways may
284+ * populate any subset depending on the underlying middleware; the UI treats
285+ * them as optional metadata and falls back to ROS 2 semantics when they are
286+ * absent.
278287 */
279288interface RawDataItem {
280289 id : string ;
281290 name ?: string ;
282291 category ?: string ;
292+ /** Current value inlined by the gateway when available. */
293+ value ?: unknown ;
283294 'x-medkit' ?: {
295+ /** Middleware identifier (e.g. 'ros2'); consumers treat any other value as non-ROS 2. */
296+ middleware ?: string ;
297+ /** Access mode ('read' | 'write' | 'readwrite'). */
298+ access ?: string ;
299+ /** Vendor-provided type label, used when no ROS 2 message type is available. */
300+ type ?: string ;
301+ /** Direction: 'publish'/'subscribe'/'both' or 'input'/'output' as alternative terms. */
302+ direction ?: string ;
284303 ros2 ?: { topic ?: string ; type ?: string ; direction ?: string } ;
285304 type_info ?: { schema ?: unknown ; default_value ?: unknown } ;
286305 } ;
@@ -290,30 +309,40 @@ interface RawDataItem {
290309 * Transform the raw data list response into `ComponentTopic[]`.
291310 *
292311 * Extracts topic metadata (type, direction, schema) from the `x-medkit` extension.
312+ * When the gateway inlines a `value`, the resulting topic is marked as `status:
313+ * 'data'` so that non-streaming middlewares render their current value immediately.
293314 */
294315export function transformDataResponse ( rawData : unknown ) : ComponentTopic [ ] {
295316 if ( ! rawData || typeof rawData !== 'object' ) return [ ] ;
296317 const dataItems = unwrapItems < RawDataItem > ( rawData ) ;
297318 return dataItems . map ( ( item ) => {
298- const rawTypeInfo = item [ 'x-medkit' ] ?. type_info ;
319+ const xm = item [ 'x-medkit' ] ;
320+ const rawTypeInfo = xm ?. type_info ;
299321 const convertedSchema = rawTypeInfo ?. schema ? convertJsonSchemaToTopicSchema ( rawTypeInfo . schema ) : undefined ;
300- const direction = item [ 'x-medkit' ] ?. ros2 ?. direction ;
301- const topicName = item . name || item [ 'x-medkit' ] ?. ros2 ?. topic || item . id ;
322+ // `input`/`output` are alternative direction terms used by non-ROS 2 middlewares.
323+ const direction = xm ?. ros2 ?. direction ?? xm ?. direction ;
324+ const topicName = item . name || xm ?. ros2 ?. topic || item . id ;
325+ // Prefer the ROS 2 message type when present so canonical topics stay
326+ // recognisable; the generic vendor label only fills the gap when no
327+ // ROS 2 type was published. This keeps precedence consistent with
328+ // `direction` above.
329+ const typeLabel = xm ?. ros2 ?. type ?? xm ?. type ;
330+ const hasValue = item . value !== undefined ;
302331 return {
303332 topic : topicName ,
304333 timestamp : Date . now ( ) ,
305- data : null ,
306- status : ' metadata_only' as const ,
307- type : item [ 'x-medkit' ] ?. ros2 ?. type ,
334+ data : hasValue ? item . value : null ,
335+ status : hasValue ? ( 'data' as const ) : ( ' metadata_only' as const ) ,
336+ type : typeLabel ,
308337 type_info : convertedSchema
309338 ? {
310339 schema : convertedSchema ,
311340 default_value : rawTypeInfo ?. default_value as Record < string , unknown > ,
312341 }
313342 : undefined ,
314343 // Direction-based fields for apps/functions.
315- isPublisher : direction === 'publish' || direction === 'both' ,
316- isSubscriber : direction === 'subscribe' || direction === 'both' ,
344+ isPublisher : direction === 'publish' || direction === 'both' || direction === 'output' ,
345+ isSubscriber : direction === 'subscribe' || direction === 'both' || direction === 'input' ,
317346 uniqueKey : direction ? `${ topicName } :${ direction } ` : topicName ,
318347 } ;
319348 } ) ;
@@ -339,6 +368,10 @@ interface RawConfigurationsResponse {
339368 *
340369 * All meaningful data lives in the `x-medkit` extension. The `entityId` parameter
341370 * is used as a fallback when `x-medkit` fields are absent.
371+ *
372+ * NOTE: currently only reads `x-medkit.ros2.*`. Extending the generic
373+ * middleware fallback here (parity with `transformDataResponse`) is tracked
374+ * separately.
342375 */
343376export function transformConfigurationsResponse ( rawData : unknown , entityId : string ) : ComponentConfigurations {
344377 if ( ! rawData || typeof rawData !== 'object' ) {
0 commit comments