Skip to content
Merged
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
5 changes: 5 additions & 0 deletions packages/genui/server/.npmrc
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
# Keep this package installable as a standalone server fixture even when npm
# sees peer ranges from Next/React-related packages that do not line up exactly
# with the monorepo's pinned versions. The workspace install still uses pnpm;
# this only affects npm-based installs in this package directory.
legacy-peer-deps=true
9 changes: 7 additions & 2 deletions packages/genui/server/agent/a2ui-catalog.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,8 @@
// Licensed under the Apache License Version 2.0 that can be found in the
// LICENSE file in the root directory of this source tree.

import { BASIC_CATALOG_EXAMPLES } from './a2ui-examples';
import type { A2UIExample } from './a2ui-examples';
import buttonManifest from './catalog/Button/catalog.json';
import cardManifest from './catalog/Card/catalog.json';
import checkBoxManifest from './catalog/CheckBox/catalog.json';
Expand All @@ -25,6 +27,7 @@ export interface A2UIComponentProp {
description?: string;
required?: boolean;
enums?: readonly string[];
schema?: JsonSchema;
}

export interface A2UIComponentSpec {
Expand All @@ -41,13 +44,13 @@ export interface A2UICatalog {
version?: string;
components: A2UIComponentSpec[];
extraRules?: string[];
examples?: string[];
examples?: A2UIExample[];
}

export const BASIC_CATALOG_ID =
'https://a2ui.org/specification/v0_9/basic_catalog.json';

interface JsonSchema {
export interface JsonSchema {
type?: string;
enum?: unknown;
oneOf?: JsonSchema[];
Expand Down Expand Up @@ -184,6 +187,7 @@ function componentFromManifest(
type: inferType(propSchema),
description: propSchema.description ?? '',
required: required.has(propName),
schema: propSchema,
...(enums ? { enums } : {}),
};
});
Expand All @@ -210,6 +214,7 @@ export const BASIC_CATALOG: A2UICatalog = {
'Use only components listed in this catalog; unsupported examples such as Video, AudioPlayer, DatePicker, or Checkbox are not available unless they appear here.',
'The implemented checkbox component is named "CheckBox" with a capital B.',
],
examples: BASIC_CATALOG_EXAMPLES,
};

export function renderCatalogReference(catalog: A2UICatalog): string {
Expand Down
258 changes: 258 additions & 0 deletions packages/genui/server/agent/a2ui-examples.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,258 @@
// Copyright 2026 The Lynx Authors. All rights reserved.
// Licensed under the Apache License Version 2.0 that can be found in the
// LICENSE file in the root directory of this source tree.

export interface A2UIExample {
name: string;
user: string;
messages: unknown[];
}

const BASIC_CATALOG_ID =
'https://a2ui.org/specification/v0_9/basic_catalog.json';

export const BASIC_CATALOG_EXAMPLES: A2UIExample[] = [
{
name: 'login-card',
user: 'Generate a login card with email, password, and a submit button.',
messages: [
{
version: 'v0.9',
createSurface: {
surfaceId: 'main',
catalogId: BASIC_CATALOG_ID,
},
},
{
version: 'v0.9',
updateComponents: {
surfaceId: 'main',
components: [
{ id: 'root', component: 'Card', child: 'form-column' },
{
id: 'form-column',
component: 'Column',
children: ['title', 'email', 'password', 'submit'],
},
{ id: 'title', component: 'Text', text: 'Sign in', variant: 'h2' },
{
id: 'email',
component: 'TextField',
label: 'Email',
value: { path: '/form/email' },
},
{
id: 'password',
component: 'TextField',
label: 'Password',
variant: 'obscured',
value: { path: '/form/password' },
},
{
id: 'submit',
component: 'Button',
variant: 'primary',
child: 'submit-label',
action: {
event: {
name: 'submit_login',
context: {
email: { path: '/form/email' },
password: { path: '/form/password' },
},
},
},
},
{ id: 'submit-label', component: 'Text', text: 'Sign in' },
],
},
},
{
version: 'v0.9',
updateDataModel: {
surfaceId: 'main',
value: { form: { email: '', password: '' } },
},
},
],
},
{
name: 'dynamic-list',
user: 'Show three trip ideas as a compact list.',
messages: [
{
version: 'v0.9',
createSurface: {
surfaceId: 'main',
catalogId: BASIC_CATALOG_ID,
},
},
{
version: 'v0.9',
updateComponents: {
surfaceId: 'main',
components: [
{
id: 'root',
component: 'Column',
children: ['title', 'trip-list'],
},
{
id: 'title',
component: 'Text',
text: 'Trip ideas',
variant: 'h2',
},
{
id: 'trip-list',
component: 'List',
direction: 'vertical',
children: { path: '/items', componentId: 'trip-row' },
},
{
id: 'trip-row',
component: 'Row',
children: ['trip-icon', 'trip-copy'],
align: 'center',
},
{ id: 'trip-icon', component: 'Icon', name: 'location_on' },
{
id: 'trip-copy',
component: 'Column',
children: ['trip-name', 'trip-detail'],
},
{
id: 'trip-name',
component: 'Text',
text: { path: '/items/*/name' },
variant: 'h3',
},
{
id: 'trip-detail',
component: 'Text',
text: { path: '/items/*/detail' },
variant: 'body',
},
],
},
},
{
version: 'v0.9',
updateDataModel: {
surfaceId: 'main',
path: '/items',
value: [
{ name: 'Canal walk', detail: 'Morning coffee and quiet bridges' },
{
name: 'Museum loop',
detail: 'Design exhibits plus lunch nearby',
},
{ name: 'Sunset hill', detail: 'Short climb with skyline views' },
],
},
},
],
},
{
name: 'chart-card',
user: 'Show weekly active users as a line chart.',
messages: [
{
version: 'v0.9',
createSurface: {
surfaceId: 'main',
catalogId: BASIC_CATALOG_ID,
},
},
{
version: 'v0.9',
updateComponents: {
surfaceId: 'main',
components: [
{ id: 'root', component: 'Card', child: 'chart-column' },
{
id: 'chart-column',
component: 'Column',
children: ['title', 'chart'],
},
{
id: 'title',
component: 'Text',
text: 'Weekly active users',
variant: 'h2',
},
{
id: 'chart',
component: 'LineChart',
labels: { path: '/chart/labels' },
series: { path: '/chart/series' },
xLabel: 'Day',
yLabel: 'Users',
showGrid: true,
showLegend: true,
},
],
},
},
{
version: 'v0.9',
updateDataModel: {
surfaceId: 'main',
value: {
chart: {
labels: ['Mon', 'Tue', 'Wed', 'Thu', 'Fri'],
series: [{ name: 'Users', values: [120, 148, 132, 171, 190] }],
},
},
},
},
],
},
{
name: 'action-update',
user:
'A2UI_USER_ACTION: {"surfaceId":"main","action":{"name":"submit_login","context":{"email":"me@example.com"}}}',
messages: [
{
version: 'v0.9',
updateDataModel: {
surfaceId: 'main',
path: '/status',
value: {
kind: 'success',
message: 'Signed in as me@example.com',
},
},
},
{
version: 'v0.9',
updateComponents: {
surfaceId: 'main',
components: [
{
id: 'root',
component: 'Card',
child: 'status-column',
},
{
id: 'status-column',
component: 'Column',
children: ['status-title', 'status-message'],
},
{
id: 'status-title',
component: 'Text',
text: 'Success',
variant: 'h2',
},
{
id: 'status-message',
component: 'Text',
text: { path: '/status/message' },
},
],
},
},
],
},
];
Loading
Loading