@ a2ui/ 反应
A2UI(代理对用户界面)的反相渲染器 - 允许AI代理 通过声明式的JSON生成丰富的交互式用户界面.
特征
- v0.9 土著: 专门为A2UI v0.9协议所建造,并有更好的模块性和类型安全性.
- 深度反应:由A2UI通用Binder提供动力,用于自动,精细的更新.
- 强键:从Zod schemas中推导出的财产类型确保了编译时的安全.
- 广泛: 容易定义自定义组件目录和逻辑函数.
- 多面质: 内建支持管理独立的UI表面.
安装
yarn add @a2ui/react @a2ui/web_core
协议版本
A2UI支持多个协议版本以确保后向相容. 对于新项目,建议使用 页:1 协议.
要使用 v0. 9 执行, 从版本路径导入 :
import {A2uiSurface} from '@a2ui/react/v0_9';
import {basicCatalog} from '@a2ui/web_core/v0_9/basic_catalog';
快速启动
反应渲染器与 MessageProcessor 从 @a2ui/web_core. 处理器从一个AI代理解析出JSON消息,并管理由此产生的UI状态. 核心概念是:
- 处理器 ——接收和解读代理消息.
- 表面 ——一个独立渲染区域,由字符串ID独有地识别出,由代理创建并配有组件.
- 目录 ——一组组件(如.
Text, (中文(简体) ),Column, (中文(简体) ),Button供表面使用.
下面的例子创建一个处理器,其中包含 basicCatalog 从 @a2ui/web_core,输入一系列被硬编码的信息,使产生的表面.
import {useState, useEffect} from 'react';
import {MessageProcessor} from '@a2ui/web_core/v0_9';
import {basicCatalog} from '@a2ui/web_core/v0_9/basic_catalog';
import {A2uiSurface} from '@a2ui/react/v0_9';
export default function App() {
// 1. Create the processor and feed it messages.
const [processor] = useState(() => {
const p = new MessageProcessor([basicCatalog]);
p.processMessages(sampleAgentMessages);
return p;
});
// 2. Set up listeners to keep the UI up to date as messages arrive.
const [surfaces, setSurfaces] = useState(() => Array.from(processor.model.surfacesMap.values()));
useEffect(() => {
const sync = () => setSurfaces(Array.from(processor.model.surfacesMap.values()));
const createdSub = processor.onSurfaceCreated(sync);
const deletedSub = processor.onSurfaceDeleted(sync);
return () => {
createdSub.unsubscribe();
deletedSub.unsubscribe();
};
}, [processor]);
// 3. Render every surface the agent has created.
return (
<div className="a2ui-container">
{surfaces.length === 0 && <div>Waiting for agent...</div>}
{surfaces.map(surface => (
<A2uiSurface key={surface.id} surface={surface} />
))}
</div>
);
}
// In a real app, these messages would come from an agent via WebSocket, SSE, etc.
// Here we hardcode them to show the message format.
const sampleAgentMessages = [
{
version: 'v0.9' as const,
createSurface: {surfaceId: 'main-chat', catalogId: basicCatalog.id},
},
{
version: 'v0.9' as const,
updateComponents: {
surfaceId: 'main-chat',
components: [
{id: 'root', component: 'Column', children: ['greeting', 'description']},
{id: 'greeting', component: 'Text', text: {path: '/title'}},
{id: 'description', component: 'Text', text: {path: '/body'}},
],
},
},
{
version: 'v0.9' as const,
updateDataModel: {
surfaceId: 'main-chat',
path: '/',
value: {
title: 'Hello from A2UI!',
body: 'Replace these messages with real agent responses to build interactive UIs.',
},
},
},
];
运行此示例应显示“ 来自 A2UI! ” 。 这个例子显示了三种信息类型:
createSurface初始化渲染表面.updateComponents定义 UI 树。 这里,一个Column包含两个Text组件.updateDataModel提供组件通过下列方式引用的数据:path约束 (例如:.{ path: '/title' }决定:title字段.
定义自定义组件
A2UI v0.9 严格将组件的API(Schema)与其执行相分离.
1. 界定组成部分API
使用 Zod 定义属性 。 使用 CommonSchemas 从 web_core 允许自动装入 A2UI 原始文件 .
import {z} from 'zod';
import {CommonSchemas} from '@a2ui/web_core/v0_9';
export const MyProfileApi = {
name: 'Profile',
schema: z.object({
username: CommonSchemas.DynamicString, // Can be literal "Alice" or {path: "/user/name"}
bio: CommonSchemas.DynamicString,
avatarUrl: CommonSchemas.DynamicString,
onEdit: CommonSchemas.Action, // Resolves to a clickable () => void
isEditable: CommonSchemas.DynamicBoolean,
// Add 'checks' if you want validation support (standard in v0.9 interactive components)
checks: CommonSchemas.Checkable.shape.checks,
}),
};
API也可以限制组件出现的地方,使用 allowedParents 财务报告和审定财务报表 allowedChildren 组件名称列表。 消息处理器然后拒绝将组件置于另一个母体之下的有效载荷 UNALLOWED_PARENT,或者给它一个与 UNALLOWED_CHILD中。根组件的父为 Surface。仅以 CommonSchemas.ComponentId 或者说 CommonSchemas.ChildList 抱着孩子,在平地上 z.string() 不检查属性 allowedChildren。 。 。 .
2. 创建反应执行
这个 createComponentImplementation 工厂使用 普通宾德 在组件生成前解决所有动态值.
import {createComponentImplementation} from '@a2ui/react/v0_9';
export const MyProfile = createComponentImplementation(MyProfileApi, ({props, buildChild}) => {
// 'props' is strictly inferred from the Zod schema:
// props.username is 'string' (resolved from DynamicString)
// props.onEdit is '() => void' (resolved from Action)
return (
<div className="profile-widget">
<img src={props.avatarUrl ?? ''} alt={props.username} />
<h2>{props.username}</h2>
<p>{props.bio}</p>
{props.isEditable && (
<button onClick={props.onEdit} disabled={props.isValid === false}>
Edit Profile
</button>
)}
{/* Render validation errors if any check fails */}
{props.validationErrors?.map((err, i) => (
<div key={i} className="error-hint" style={{color: 'red'}}>
{err}
</div>
))}
</div>
);
});
一般宾德特征
通用Binder是一款框架不可知引擎,将生JSON有效载荷配置转化为由强型道具组成的有凝聚力的反应流.
- 自动解析属性:
DynamicString, (中文(简体) ),DynamicNumber,以及DynamicBoolean自动解为当前值(字符串、数字、布尔值). - 双向绑定: 如果一个计划使用动态类型( 如
DynamicString),绑定器会自动注入设置器。 为了财产username,它补充props.setUsername(val: string),它更新了基础数据模型. - 行动背景数字 :
Action属性被解为即时调用功能。 当被调用时,它们会在通知服务器前自动解析其深层上下文绑定(如从模型中收集形式数据). - 嵌入值:列表和对象是逐项解决的,所以一个动作,绑定或列表内的孩子列表会像在顶层解决一样,其道具会这样打入.
- 反应验证:如果您的计划包含
checks,绑定器反应性地评估规则并注入props.isValid财务报告和审定财务报表props.validationErrors基于逻辑函数的结果.
无铜元件
用于高级使用时需要直接访问 ComponentContext 或想要手动管理反应(例如,用于性能关键动画),使用 createBinderlessComponentImplementation。 。 。 .
import {createBinderlessComponentImplementation} from '@a2ui/react/v0_9';
export const RawInspector = createBinderlessComponentImplementation(InspectorApi, ({context}) => {
// Access the raw, unresolved component model and the data model directly
const rawData = context.componentModel.properties;
const componentId = context.componentModel.id;
return (
<details>
<summary>Raw Component State (ID: {componentId})</summary>
<pre>{JSON.stringify(rawData, null, 2)}</pre>
</details>
);
});
定义目录和函数
将您的组件和逻辑函数分组为 Catalog 用于: MessageProcessor。 。 。 .
import {Catalog, createFunctionImplementation} from '@a2ui/web_core/v0_9';
import {z} from 'zod';
// 1. Implement a custom logic function
const myCheckFunc = createFunctionImplementation(
{
name: 'is_admin',
returnType: 'boolean',
schema: z.object({role: z.string()}),
},
args => args.role === 'admin',
);
// 2. Compose the catalog
export const myCatalog = new Catalog(
'https://example.com/catalogs/v1.json',
'v0.9', // Protocol version the catalog targets
[MyProfile, RawInspector], // List of ReactComponentImplementation
[myCheckFunc], // List of FunctionImplementation
);
基本目录组件
@a2ui/web_core/v0_9/basic_catalog 页:1 basicCatalog 带有标准组件。 它们是W3C自定义元素,反应渲染器使它们成为元素:
- 版式数字 :
Row, (中文(简体) ),Column, (中文(简体) ),List, (中文(简体) ),Card, (中文(简体) ),Tabs, (中文(简体) ),Modal, (中文(简体) ),Divider - 内容数字 :
Text, (中文(简体) ),Image, (中文(简体) ),Icon, (中文(简体) ),Video, (中文(简体) ),AudioPlayer - 投入数字 :
Button, (中文(简体) ),TextField, (中文(简体) ),CheckBox, (中文(简体) ),ChoicePicker, (中文(简体) ),Slider, (中文(简体) ),DateTimeInput
输入 Text
Text 由应用程序提供的渲染器来制作它 给 MarkdownContext 一个返回 HTML 的函数,例如来自 @a2ui/markdown-it,或给予 MarkdownComponentContext a 反应组件:
import {A2uiSurface, MarkdownComponentContext} from '@a2ui/react/v0_9';
const ChatMarkdown = ({markdown}: {markdown: string}) => <Markdown text={markdown} />;
<MarkdownComponentContext.Provider value={ChatMarkdown}>
<A2uiSurface surface={surface} />
</MarkdownComponentContext.Provider>;
组件在其中 Text,作为应用的回放树的一部分,所以它读取了应用的上下文. 当两者都给出时,则使用组件. Text 读取整个页面的 Markdown 渲染器, 将组件给每个 A2uiSurface 页面或无.
造型和CSS模块
基本目录组件是自成一体的,并使用暴露于 @a2ui/web_core。 。 。 .
您可以使用 CSS 模块来设计您的自定义组件 。 大多数现代反应环境(如Vite,Next.js,和Create React App)都支持出框. 必须配置自定义的构建设置来处理 .module.css 文档,例如 css-loader 在 Webpack 中启用模块.
/* MyComponent.module.css */
.myComponent {
display: flex;
gap: var(--a2ui-spacing-m, 8px);
}
/* Use :global to target nested elements (like those generated by Markdown) */
.myComponent :global(p) {
color: var(--a2ui-color-on-background);
}
import styles from './MyComponent.module.css';
export const MyComponent = createComponentImplementation(MyComponentApi, ({props}) => {
return <div className={styles.myComponent}>{/* ... */}</div>;
});
遗产支助(v0.8)
A2UI v0.8 为后向相容性维护. 虽然它仍然是默认导出 @a2ui/react 软件包,建议为类型安全绑定器和逻辑函数等新特性向v0.9过渡.
导入和使用
要使用 v0.8 渲染器,请使用 A2UIProvider 财务报告和审定财务报表 A2UIRenderer 组件 :
import {A2UIProvider, A2UIRenderer, injectStyles} from '@a2ui/react/v0_8';
// Inject v0.8 styles
injectStyles();
function LegacyApp() {
const handleAction = msg => console.log('Action:', msg);
return (
<A2UIProvider onAction={handleAction}>
{/* Renders the surface using v0.8 logic */}
<A2UIRenderer surfaceId="main" />
</A2UIProvider>
);
}
密钥差异( v0. 8 vs v
| 特性 | v0.8 (语言) | v0.9 (当前) |
|---|---|---|
| 议定书 | 用途 BeginRendering, (中文(简体) ), SurfaceUpdate。 。 。 . | 用途 createSurface, (中文(简体) ), updateComponents, (中文(简体) ), updateDataModel。 。 。 . |
| 数据流动 | 单向地表更新 . | 双向同步sendDataModel) (中文(简体) ). |
| 类型安全 | 通过 node.properties。 。 。 . | 强键 props 根据Zod计划推断. |
| 逻辑 | 有限客户端逻辑. | 广泛 Function 系统(例如, formatString, (中文(简体) ), required) (中文(简体) ). |
| 反应 | 基于虎克( C)useA2UIComponent) (中文(简体) ). | 自动通过 普通宾德 中间软件. |
| 装订 | 手工解析成组件正文. | 声明式双向绑定与注射定子. |
在v0.8中,组件负责用钩子解决自身的动态值:
// v0.8 Manual Resolution
function TextField({node, surfaceId}) {
const {resolveString, setValue} = useA2UIComponent(node, surfaceId);
const label = resolveString(node.properties.label);
// ...
}
在v0.9中,这是由 普通宾德 在组件甚至制作之前,生成更清洁的框架内置视图代码.
警卫
[大 提供的样本代码用于演示,并说明了A2UI的力学. 在建立生产应用程序时,关键是要将任何在您直接控制之外运作的代理商视为一个潜在的不信任实体.
外部代理机构提供的所有业务数据,包括其信息和UI定义,应作为不信任的投入处理。 恶意代理可能试图对合法接口进行套用来欺骗用户(fishing),通过属性值(XSS)来注入恶意脚本,或者产生过度的布局复杂来降低客户端性能(DoS). 如果您的应用程序支持可选的嵌入内容(如iframes或web视图),则必须额外注意防止被恶意外部网站曝光.
开发者责任:不能正确验证数据和严格地提供沙盒内容可能会造成严重的脆弱性。 开发者负责执行适当的安全措施——例如输入消毒、内容安全政策和确保证书处理——以保护他们的系统和用户.
发展
设置
# In the A2UI monorepo root
yarn install
构建
yarn build # Build the package
yarn dev # Watch mode
类型检查
yarn typecheck
林特
yarn lint
测试
单位测试
yarn test # Run once
yarn test:watch # Watch mode
结构 : tests/ ├── setup.ts # Initializes component catalog ├── helpers.tsx # TestWrapper, TestRenderer, message creators └── components/ # Component tests (*.test.tsx)
示例 { tsx 导入{ 渲染、屏幕、 fireEvent} 从 '@ testing-library/ react'; 导入 { testWrapper, TestRender, 创建“./ 帮助者” 的简单消息;
它( 应该在点击时发出动作) , () { { const on Action = v.fn (); const 信件 = 创建 SimpleMessages ("btn 1","按钮",{子:"text-1",动作:{ 名称:“提交”},});
渲染( c) (三);
fireEvent.click(屏幕.getByRole ("按钮")) ; 期望( 关于行动 ) 。 要呼叫( ) ; ) ; @%%
视觉对等测试
React 渲染器与 Lit 渲染器保持视觉等同( 参考) (执行)。 综合测试套件比较像素完美截图 在两个制造器之间.
运行视觉对等测试
cd visual-parity
yarn test
快速命令
# Run all tests
yarn test
# Run specific component tests
yarn test --grep "button"
# Run with UI mode
yarn test:ui
# Start dev servers for manual inspection
yarn dev
# React: http://localhost:5001
# Lit: http://localhost:5002
文档
- 视觉平等/README.md - 测试套房的使用 和固定的创建
- 视觉-平面/平面 - CSS系统 a. 改革办法和执行状况
关键概念
- 结构镜像: 反应组件镜像 Lit 的阴影 DOM 结构
- CSS 选择器转换数字 :
:host→.a2ui-surface .a2ui-{component} - 特性匹配: 用途
:where()以匹配 Lit 的低特异性