Skip to content

Commit 4b1a632

Browse files
committed
feat(ui-protocol): A2UI v0.9 alignment enhancement
- Add createSurface message with catalogId support - Add DataModelOperation (add/replace/remove) for data updates - Add Button actionContext for automatic form data collection - Add ValidationError format for LLM self-correction - Add ClientMessage types (UserActionMessage, ProtocolError) - Add simplified PropertyValue format (A2UI compatible) - Enhance UIActionEvent with timestamp and context fields - Add comprehensive unit tests and property tests (173+ new tests) - Update documentation with all new features Closes: UI Protocol A2UI Alignment Spec
1 parent 854616c commit 4b1a632

25 files changed

+3866
-102
lines changed

CHANGELOG.md

Lines changed: 72 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,77 @@
11
# Changelog
22

3+
## [v0.35.0] - 2025-12-29
4+
5+
### Added
6+
7+
- **UI Protocol A2UI v0.9 对齐增强**
8+
- `createSurface` 消息类型:支持创建 Surface 并指定 `catalogId` 组件目录
9+
- `DataModelOperation` 操作类型:支持 `add`(追加/合并)、`replace`(替换)、`remove`(删除)三种数据操作
10+
- `actionContext` 按钮属性:点击时自动解析路径引用,收集表单数据到 `UIActionEvent.context`
11+
- `ValidationError` 标准格式:JSON Pointer 路径指向错误位置,便于 LLM 自我纠正
12+
- `ClientMessage` 类型:`UserActionMessage``ProtocolError` 客户端到服务端消息
13+
- 简化 `PropertyValue` 格式:支持 A2UI 风格直接字面值(string/number/boolean)
14+
- `UIActionEvent` 增强:添加 `timestamp`(ISO 8601)和 `context` 字段
15+
16+
- **Go 类型定义** (`pkg/types/ui_protocol.go`)
17+
- `DataModelOperation` 枚举类型
18+
- `CreateSurfaceMessage` 结构体
19+
- `ClientMessage``UserActionMessage` 类型
20+
- `ProtocolError``ValidationError` 错误类型
21+
- `ButtonProps.ActionContext` 字段
22+
- `UIActionEvent.Timestamp``UIActionEvent.Context` 字段
23+
24+
- **TypeScript 类型定义** (`ui/src/types/ui-protocol.ts`)
25+
- 完整的 A2UI 对齐类型定义
26+
- `parseExtendedPropertyValue()``normalizePropertyValue()` 工具函数
27+
- `createUIActionEvent()``createUserActionMessage()` 工厂函数
28+
- `createValidationError()``createGenericError()` 错误创建函数
29+
30+
- **MessageProcessor 增强** (`ui/src/protocol/message-processor.ts`)
31+
- `processCreateSurface()` 方法
32+
- `validateMessage()` 消息验证方法
33+
- `addDataToSurface()``removeDataFromSurface()` 数据操作方法
34+
- `resolveActionContext()` 上下文解析方法
35+
- Surface `catalogId` 存储支持
36+
37+
- **Client Message 模块** (`ui/src/protocol/client-message.ts`)
38+
- `createUserActionMessage()` 用户动作消息创建
39+
- `createErrorMessage()` 错误消息创建
40+
- `resolveActionContext()` 路径引用解析
41+
- `serializeClientMessage()``parseClientMessage()` 序列化函数
42+
43+
- **Path Resolver 增强** (`ui/src/protocol/path-resolver.ts`)
44+
- `addData()` 函数:数组追加、对象合并、路径创建
45+
- `removeData()` 函数:值删除、数组元素删除并重新索引
46+
47+
### Changed
48+
49+
- **AsterButton 组件**:支持 `actionContext` 属性,点击时自动解析并包含在事件中
50+
- **useUIAction composable**:使用 `createUIActionEvent()` 生成标准格式事件
51+
52+
### Tests
53+
54+
- 新增 8 个测试文件,共 173+ 新测试用例
55+
- `data-operations.spec.ts` - 数据模型操作单元测试
56+
- `action-context.spec.ts` - Action Context 解析测试
57+
- `property-value-parsing.spec.ts` - 简化属性值格式测试
58+
- `create-surface.spec.ts` - CreateSurface 消息测试
59+
- `validation-error.spec.ts` - 验证错误格式测试
60+
- `data-operations.property.spec.ts` - 数据操作属性测试 (Property 17, 18)
61+
- `action-context.property.spec.ts` - Action Context 属性测试 (Property 19)
62+
- `property-value.property.spec.ts` - 属性值兼容性测试 (Property 20)
63+
- Go 类型测试:12 个新测试用例覆盖所有 A2UI 类型
64+
65+
### Documentation
66+
67+
- 更新 UI Protocol 文档 (`docs/content/02.core-concepts/19.ui-protocol.md`)
68+
- 添加 `createSurface` 消息说明
69+
- 添加数据模型操作类型 (add/replace/remove) 说明
70+
- 添加 Action Context 使用示例
71+
- 添加简化属性值格式说明
72+
- 添加验证错误格式说明
73+
- 添加 Client-to-Server 消息说明
74+
375
## [v0.33.0] - 2025-12-28
476

577
### Added

docs/content/02.core-concepts/19.ui-protocol.md

Lines changed: 143 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -40,10 +40,11 @@ Aster UI Protocol 是一套声明式 UI 协议,借鉴 Google A2UI 的设计理
4040

4141
## 📦 消息类型
4242

43-
UI Protocol 支持四种消息操作
43+
UI Protocol 支持五种消息操作
4444

4545
| 操作类型 | 用途 | 事件类型 |
4646
|---------|------|---------|
47+
| `createSurface` | 创建 Surface | `ui:create_surface` |
4748
| `surfaceUpdate` | 更新组件定义 | `ui:surface_update` |
4849
| `dataModelUpdate` | 更新数据模型 | `ui:data_update` |
4950
| `beginRendering` | 开始渲染 | `ui:surface_update` |
@@ -54,12 +55,19 @@ UI Protocol 支持四种消息操作:
5455
```go
5556
// AsterUIMessage 主消息结构
5657
type AsterUIMessage struct {
58+
CreateSurface *CreateSurfaceMessage `json:"createSurface,omitempty"`
5759
SurfaceUpdate *SurfaceUpdateMessage `json:"surfaceUpdate,omitempty"`
5860
DataModelUpdate *DataModelUpdateMessage `json:"dataModelUpdate,omitempty"`
5961
BeginRendering *BeginRenderingMessage `json:"beginRendering,omitempty"`
6062
DeleteSurface *DeleteSurfaceMessage `json:"deleteSurface,omitempty"`
6163
}
6264

65+
// CreateSurfaceMessage 创建 Surface(A2UI 对齐)
66+
type CreateSurfaceMessage struct {
67+
SurfaceID string `json:"surfaceId"`
68+
CatalogID string `json:"catalogId,omitempty"` // 组件目录标识符
69+
}
70+
6371
// SurfaceUpdateMessage 更新组件
6472
type SurfaceUpdateMessage struct {
6573
SurfaceID string `json:"surfaceId"`
@@ -68,19 +76,58 @@ type SurfaceUpdateMessage struct {
6876

6977
// DataModelUpdateMessage 更新数据
7078
type DataModelUpdateMessage struct {
71-
SurfaceID string `json:"surfaceId"`
72-
Path string `json:"path,omitempty"` // JSON Pointer 路径
73-
Contents any `json:"contents"`
79+
SurfaceID string `json:"surfaceId"`
80+
Path string `json:"path,omitempty"` // JSON Pointer 路径
81+
Op DataModelOperation `json:"op,omitempty"` // add/replace/remove
82+
Contents any `json:"contents,omitempty"`
7483
}
7584

85+
// DataModelOperation 数据操作类型(A2UI 对齐)
86+
type DataModelOperation string
87+
const (
88+
DataModelOperationAdd DataModelOperation = "add"
89+
DataModelOperationReplace DataModelOperation = "replace"
90+
DataModelOperationRemove DataModelOperation = "remove"
91+
)
92+
7693
// BeginRenderingMessage 开始渲染
7794
type BeginRenderingMessage struct {
7895
SurfaceID string `json:"surfaceId"`
7996
Root string `json:"root"` // 根组件 ID
8097
Styles map[string]string `json:"styles,omitempty"` // CSS 自定义属性
98+
CatalogID string `json:"catalogId,omitempty"` // 可覆盖 createSurface 的值
8199
}
82100
```
83101

102+
### 数据模型操作(A2UI 对齐)
103+
104+
支持三种操作类型:
105+
106+
```go
107+
// add - 追加到数组或合并到对象
108+
emitter.Emit(&types.ProgressUIDataUpdateEvent{
109+
SurfaceID: "surface",
110+
Path: "/items",
111+
Op: types.DataModelOperationAdd,
112+
Contents: "new-item", // 追加到数组
113+
})
114+
115+
// replace - 替换值(默认行为)
116+
emitter.Emit(&types.ProgressUIDataUpdateEvent{
117+
SurfaceID: "surface",
118+
Path: "/user/name",
119+
Op: types.DataModelOperationReplace,
120+
Contents: "Bob",
121+
})
122+
123+
// remove - 删除值
124+
emitter.Emit(&types.ProgressUIDataUpdateEvent{
125+
SurfaceID: "surface",
126+
Path: "/items/0",
127+
Op: types.DataModelOperationRemove,
128+
})
129+
```
130+
84131
## 🧩 组件系统
85132

86133
### 邻接表模型
@@ -126,6 +173,54 @@ type PropertyValue struct {
126173
}
127174
```
128175

176+
### 简化属性值格式(A2UI 兼容)
177+
178+
除了标准格式,还支持 A2UI 风格的简化格式:
179+
180+
```typescript
181+
// 标准格式
182+
{ literalString: "Hello" }
183+
{ literalNumber: 42 }
184+
{ literalBoolean: true }
185+
{ path: "/user/name" }
186+
187+
// A2UI 简化格式(同样支持)
188+
"Hello" // 等价于 { literalString: "Hello" }
189+
42 // 等价于 { literalNumber: 42 }
190+
true // 等价于 { literalBoolean: true }
191+
{ path: "/user/name" } // 路径引用格式相同
192+
```
193+
194+
### Button Action Context(A2UI 对齐)
195+
196+
按钮支持 `actionContext` 属性,点击时自动收集表单数据:
197+
198+
```go
199+
ButtonProps{
200+
Label: PropertyValue{LiteralString: ptr("提交")},
201+
Action: "submit-form",
202+
ActionContext: map[string]PropertyValue{
203+
"userName": {Path: ptr("/form/name")}, // 自动解析路径
204+
"formId": {LiteralString: ptr("form-1")}, // 字面值
205+
},
206+
}
207+
```
208+
209+
点击时生成的 `UIActionEvent` 会包含解析后的 `context`
210+
211+
```typescript
212+
interface UIActionEvent {
213+
surfaceId: string;
214+
componentId: string;
215+
action: string;
216+
timestamp: string; // ISO 8601 格式
217+
context: { // 解析后的 actionContext
218+
userName: "Alice",
219+
formId: "form-1"
220+
};
221+
}
222+
```
223+
129224
## 🔗 数据绑定
130225

131226
使用 JSON Pointer 语法绑定数据:
@@ -307,6 +402,50 @@ registry.register('MyChart', MyChartComponent, 'my-chart')
307402

308403
## 🔒 安全性
309404

405+
### 验证错误格式(A2UI 对齐)
406+
407+
消息验证失败时返回标准格式的错误,便于 LLM 自我纠正:
408+
409+
```go
410+
// ValidationError 验证错误
411+
type ProtocolError struct {
412+
Code string `json:"code"` // "VALIDATION_FAILED"
413+
SurfaceID string `json:"surfaceId"`
414+
Path string `json:"path"` // JSON Pointer 指向错误位置
415+
Message string `json:"message"`
416+
Details map[string]any `json:"details,omitempty"`
417+
}
418+
419+
// 示例错误
420+
{
421+
"code": "VALIDATION_FAILED",
422+
"surfaceId": "form-surface",
423+
"path": "/dataModelUpdate/contents",
424+
"message": "contents is required for add operation"
425+
}
426+
```
427+
428+
### Client-to-Server 消息(A2UI 对齐)
429+
430+
客户端发送用户交互事件:
431+
432+
```go
433+
// ClientMessage 客户端消息
434+
type ClientMessage struct {
435+
UserAction *UserActionMessage `json:"userAction,omitempty"`
436+
Error *ProtocolError `json:"error,omitempty"`
437+
}
438+
439+
// UserActionMessage 用户动作
440+
type UserActionMessage struct {
441+
Name string `json:"name"`
442+
SurfaceID string `json:"surfaceId"`
443+
SourceComponentID string `json:"sourceComponentId"`
444+
Timestamp string `json:"timestamp"` // ISO 8601
445+
Context map[string]any `json:"context"`
446+
}
447+
```
448+
310449
### 白名单机制
311450

312451
只有注册的组件类型才能被渲染:

0 commit comments

Comments
 (0)