Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
48 changes: 28 additions & 20 deletions packages/genui/lib/src/model/a2ui_message.dart
Original file line number Diff line number Diff line change
Expand Up @@ -89,36 +89,44 @@ sealed class A2uiMessage {
/// Returns the JSON schema for an A2UI message.
static Schema a2uiMessageSchema(Catalog catalog) {
return S.combined(
allOf: [
title: 'A2UI Message Schema',
description:
'Describes a JSON payload for an A2UI (Agent to UI) message, '
'which is used to dynamically construct and update user interfaces.',
oneOf: [
S.object(
title: 'A2UI Message Schema',
description:
'Describes a JSON payload for an A2UI (Agent to UI) message. '
'A message MUST contain exactly ONE of the action properties.',
properties: {
'version': S.string(constValue: 'v0.9'),
'createSurface': A2uiSchemas.createSurfaceSchema(),
},
required: ['version', 'createSurface'],
additionalProperties: false,
),
S.object(
properties: {
'version': S.string(constValue: 'v0.9'),
'updateComponents': A2uiSchemas.updateComponentsSchema(catalog),
},
required: ['version', 'updateComponents'],
additionalProperties: false,
),
S.object(
properties: {
'version': S.string(constValue: 'v0.9'),
'updateDataModel': A2uiSchemas.updateDataModelSchema(),
},
required: ['version', 'updateDataModel'],
additionalProperties: false,
),
S.object(
properties: {
'version': S.string(constValue: 'v0.9'),
'deleteSurface': A2uiSchemas.deleteSurfaceSchema(),
},
required: ['version'],
required: ['version', 'deleteSurface'],
additionalProperties: false,
),
],
anyOf: [
{
'required': ['createSurface'],
},
{
'required': ['updateComponents'],
},
{
'required': ['updateDataModel'],
},
{
'required': ['deleteSurface'],
},
],
);
Comment on lines 91 to 130
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

medium

To improve maintainability and reduce code duplication, you could extract the creation of each message variant into a local helper function. This would make the oneOf list cleaner and easier to read.

    Schema messageVariant(String action, Schema actionSchema) {
      return S.object(
        properties: {
          'version': S.string(constValue: 'v0.9'),
          action: actionSchema,
        },
        required: ['version', action],
        additionalProperties: false,
      );
    }

    return S.combined(
      title: 'A2UI Message Schema',
      description:
          'Describes a JSON payload for an A2UI (Agent to UI) message, '
          'which is used to dynamically construct and update user interfaces.',
      oneOf: [
        messageVariant(
          'createSurface',
          A2uiSchemas.createSurfaceSchema(),
        ),
        messageVariant(
          'updateComponents',
          A2uiSchemas.updateComponentsSchema(catalog),
        ),
        messageVariant(
          'updateDataModel',
          A2uiSchemas.updateDataModelSchema(),
        ),
        messageVariant(
          'deleteSurface',
          A2uiSchemas.deleteSurfaceSchema(),
        ),
      ],
    );

}
}
Expand Down
21 changes: 21 additions & 0 deletions packages/genui/lib/src/model/a2ui_schemas.dart
Original file line number Diff line number Diff line change
Expand Up @@ -398,6 +398,11 @@ abstract final class A2uiSchemas {

/// Schema for a createSurface message.
static Schema createSurfaceSchema() => S.object(
description:
Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Wow, this will likely improve inference performance!

'Signals the client to create a new surface and begin rendering it. '
"When this message is sent, the client will expect 'updateComponents' "
"and/or 'updateDataModel' messages for the same surfaceId that define "
'the component tree.',
properties: {
surfaceIdKey: S.string(description: 'The unique ID for the surface.'),
'catalogId': S.string(description: 'The URI of the component catalog.'),
Expand All @@ -414,12 +419,21 @@ abstract final class A2uiSchemas {

/// Schema for a deleteSurface message.
static Schema deleteSurfaceSchema() => S.object(
description:
"Signals the client to delete the surface identified by 'surfaceId'. "
'The createSurface message MUST have been previously sent with the '
"'catalogId' that is in this message.",
properties: {surfaceIdKey: S.string()},
required: [surfaceIdKey],
);

/// Schema for a updateDataModel message.
static Schema updateDataModelSchema() => S.object(
description:
'Updates the data model for an existing surface. This message can be '
'sent multiple times to update the data model. The createSurface '
"message MUST have been previously sent with the 'catalogId' that is "
'in this message.',
properties: {
surfaceIdKey: S.string(),
'path': S.combined(type: JsonType.string, defaultValue: '/'),
Expand All @@ -445,6 +459,13 @@ abstract final class A2uiSchemas {
.toList();

return S.object(
description:
'Updates a surface with a new set of components. This message can '
'be sent multiple times to update the component tree of an existing '
'surface. One of the components in one of the components lists MUST '
"have an 'id' of 'root' to serve as the root of the component tree. "
'The createSurface message MUST have been previously sent with the '
"'catalogId' that is in this message.",
properties: {
surfaceIdKey: S.string(
description: 'The unique identifier for the UI surface.',
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -127,18 +127,19 @@ When constructing UI, you must output a VALID A2UI JSON object representing one

-----A2UI_JSON_SCHEMA_START-----
{
"allOf": [
"title": "A2UI Message Schema",
"description": "Describes a JSON payload for an A2UI (Agent to UI) message, which is used to dynamically construct and update user interfaces.",
"oneOf": [
{
"type": "object",
"title": "A2UI Message Schema",
"description": "Describes a JSON payload for an A2UI (Agent to UI) message. A message MUST contain exactly ONE of the action properties.",
"properties": {
"version": {
"type": "string",
"const": "v0.9"
},
"createSurface": {
"type": "object",
"description": "Signals the client to create a new surface and begin rendering it. When this message is sent, the client will expect 'updateComponents' and/or 'updateDataModel' messages for the same surfaceId that define the component tree.",
"properties": {
"surfaceId": {
"type": "string",
Expand All @@ -162,9 +163,24 @@ When constructing UI, you must output a VALID A2UI JSON object representing one
"surfaceId",
"catalogId"
]
}
},
"required": [
"version",
"createSurface"
],
"additionalProperties": false
},
{
"type": "object",
"properties": {
"version": {
"type": "string",
"const": "v0.9"
},
"updateComponents": {
"type": "object",
"description": "Updates a surface with a new set of components. This message can be sent multiple times to update the component tree of an existing surface. One of the components in one of the components lists MUST have an 'id' of 'root' to serve as the root of the component tree. The createSurface message MUST have been previously sent with the 'catalogId' that is in this message.",
"properties": {
"surfaceId": {
"type": "string",
Expand Down Expand Up @@ -253,9 +269,24 @@ When constructing UI, you must output a VALID A2UI JSON object representing one
"surfaceId",
"components"
]
}
},
"required": [
"version",
"updateComponents"
],
"additionalProperties": false
},
{
"type": "object",
"properties": {
"version": {
"type": "string",
"const": "v0.9"
},
"updateDataModel": {
"type": "object",
"description": "Updates the data model for an existing surface. This message can be sent multiple times to update the data model. The createSurface message MUST have been previously sent with the 'catalogId' that is in this message.",
"properties": {
"surfaceId": {
"type": "string"
Expand All @@ -271,9 +302,24 @@ When constructing UI, you must output a VALID A2UI JSON object representing one
"required": [
"surfaceId"
]
}
},
"required": [
"version",
"updateDataModel"
],
"additionalProperties": false
},
{
"type": "object",
"properties": {
"version": {
"type": "string",
"const": "v0.9"
},
"deleteSurface": {
"type": "object",
"description": "Signals the client to delete the surface identified by 'surfaceId'. The createSurface message MUST have been previously sent with the 'catalogId' that is in this message.",
"properties": {
"surfaceId": {
"type": "string"
Expand All @@ -285,30 +331,10 @@ When constructing UI, you must output a VALID A2UI JSON object representing one
}
},
"required": [
"version"
]
}
],
"anyOf": [
{
"required": [
"createSurface"
]
},
{
"required": [
"updateComponents"
]
},
{
"required": [
"updateDataModel"
]
},
{
"required": [
"version",
"deleteSurface"
]
],
"additionalProperties": false
}
]
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -129,18 +129,19 @@ When constructing UI, you must output a VALID A2UI JSON object representing one

-----A2UI_JSON_SCHEMA_START-----
{
"allOf": [
"title": "A2UI Message Schema",
"description": "Describes a JSON payload for an A2UI (Agent to UI) message, which is used to dynamically construct and update user interfaces.",
"oneOf": [
{
"type": "object",
"title": "A2UI Message Schema",
"description": "Describes a JSON payload for an A2UI (Agent to UI) message. A message MUST contain exactly ONE of the action properties.",
"properties": {
"version": {
"type": "string",
"const": "v0.9"
},
"createSurface": {
"type": "object",
"description": "Signals the client to create a new surface and begin rendering it. When this message is sent, the client will expect 'updateComponents' and/or 'updateDataModel' messages for the same surfaceId that define the component tree.",
"properties": {
"surfaceId": {
"type": "string",
Expand All @@ -164,9 +165,24 @@ When constructing UI, you must output a VALID A2UI JSON object representing one
"surfaceId",
"catalogId"
]
}
},
"required": [
"version",
"createSurface"
],
"additionalProperties": false
},
{
"type": "object",
"properties": {
"version": {
"type": "string",
"const": "v0.9"
},
"updateComponents": {
"type": "object",
"description": "Updates a surface with a new set of components. This message can be sent multiple times to update the component tree of an existing surface. One of the components in one of the components lists MUST have an 'id' of 'root' to serve as the root of the component tree. The createSurface message MUST have been previously sent with the 'catalogId' that is in this message.",
"properties": {
"surfaceId": {
"type": "string",
Expand Down Expand Up @@ -255,9 +271,24 @@ When constructing UI, you must output a VALID A2UI JSON object representing one
"surfaceId",
"components"
]
}
},
"required": [
"version",
"updateComponents"
],
"additionalProperties": false
},
{
"type": "object",
"properties": {
"version": {
"type": "string",
"const": "v0.9"
},
"updateDataModel": {
"type": "object",
"description": "Updates the data model for an existing surface. This message can be sent multiple times to update the data model. The createSurface message MUST have been previously sent with the 'catalogId' that is in this message.",
"properties": {
"surfaceId": {
"type": "string"
Expand All @@ -273,9 +304,24 @@ When constructing UI, you must output a VALID A2UI JSON object representing one
"required": [
"surfaceId"
]
}
},
"required": [
"version",
"updateDataModel"
],
"additionalProperties": false
},
{
"type": "object",
"properties": {
"version": {
"type": "string",
"const": "v0.9"
},
"deleteSurface": {
"type": "object",
"description": "Signals the client to delete the surface identified by 'surfaceId'. The createSurface message MUST have been previously sent with the 'catalogId' that is in this message.",
"properties": {
"surfaceId": {
"type": "string"
Expand All @@ -287,30 +333,10 @@ When constructing UI, you must output a VALID A2UI JSON object representing one
}
},
"required": [
"version"
]
}
],
"anyOf": [
{
"required": [
"createSurface"
]
},
{
"required": [
"updateComponents"
]
},
{
"required": [
"updateDataModel"
]
},
{
"required": [
"version",
"deleteSurface"
]
],
"additionalProperties": false
}
]
}
Expand Down
Loading