Files
Agent-System-Core/ui.go
weichen 626f8e1062 Add the Surface contract types, node ids, and spec validation
Why: The Generative UI proposal U2 needs a versioned, host-validated
envelope for agent-authored pages before any backend surface exists:
identity/compat/version envelopes, stable per-node ids with source
annotations, catalog-driven spec validation, and the surface.updated
projection event.

Evidence: go vet + go test in this repo (table tests cover a realistic
valid spec from the U1 trial shape, violations, limits, and old-payload
backward compatibility).

Impact: Additive only - UINode gains optional id/source (omitempty),
old card/form paths unaffected; no existing symbol changes.

Refs: Documents proposal 2026-10-10-generative-ui-plugin.md (r2, U2/U1
sections); Dev task feature/generative-ui-u2
2026-10-11 08:15:10 +00:00

173 lines
6.8 KiB
Go
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
package core
// UI schema 词汇(4.6 原则 3):设置界面、插件面板、HITL 表单、插件卡片共用
// 这套有限词汇,由前端通用渲染器渲染。插件不注入 React 组件;表达不了的高级
// 交互走 Core 契约扩展流程新增词汇,而不是开洞。
type UINodeType string
const (
UISection UINodeType = "section" // 标题 + 子节点
UIList UINodeType = "list" // 字符串列表
UIKV UINodeType = "kv" // 键值对列表
UIForm UINodeType = "form" // 字段表单(HITL form / 设置分区复用)
UIMarkdown UINodeType = "markdown"
UIDocRef UINodeType = "doc-ref" // 工件引用(右栏查看器打开)
UIActions UINodeType = "actions" // 可点动作(发命令/发消息)
UIChartLite UINodeType = "chart-lite"
// —— 收件箱/工作区扩展词汇(提案 D28;graph 远期,追溯视图按"对象为中心 +
// 分组泳道 + 逐层展开"约束设计,禁止力导向裸图)——
UIAvatar UINodeType = "avatar" // 头像(成员/责任人展示;UI 能力平台,插件可用)
UIProgress UINodeType = "progress" // 进度条(摄取/生成/填充度)
UICompare UINodeType = "compare" // 左右对比(基线 vs 新内容、diff 确认)
UITree UINodeType = "tree" // 树(文档树/笔记树骨架;节点带状态灯/徽标/计数)
UITable UINodeType = "table" // 表格(大表/切片表;行级操作)
UISteps UINodeType = "steps" // 流程步骤条(变更七步等)
UITabs UINodeType = "tabs" // 页签容器(工作区多页签)
UITimeline UINodeType = "timeline" // 时间线(版本链/批注流/事件史)
)
type UINode struct {
Type UINodeType `json:"type"`
// ID / Source 是 Generative UI Surface 层的节点级标注(提案 U2):ID 整页
// 唯一且稳定(交互与修订对位);Source 为支撑该节点事实内容的来源标识,
// 授权校验在数据绑定层(U3)。均为可选:旧卡片/表单路径不填不受影响。
ID string `json:"id,omitempty"`
Source []string `json:"source,omitempty"`
Title string `json:"title,omitempty"`
Items []string `json:"items,omitempty"` // list
KV [][2]string `json:"kv,omitempty"` // kv
Fields []UIField `json:"fields,omitempty"` // form
Markdown string `json:"markdown,omitempty"`
DocID ID `json:"docId,omitempty"` // doc-ref
Actions []UIAction `json:"actions,omitempty"`
Chart *UIChart `json:"chart,omitempty"`
Children []UINode `json:"children,omitempty"` // section
Avatar *UIAvatarSpec `json:"avatar,omitempty"` // avatar
Progress *UIProgressSpec `json:"progress,omitempty"` // progress
Compare *UICompareSpec `json:"compare,omitempty"` // compare
Tree *UITreeSpec `json:"tree,omitempty"` // tree
Table *UITableSpec `json:"table,omitempty"` // table
Steps *UIStepsSpec `json:"steps,omitempty"` // steps
Tabs *UITabsSpec `json:"tabs,omitempty"` // tabs
Timeline *UITimelineSpec `json:"timeline,omitempty"` // timeline
}
// UIAvatar:头像(成员/责任人;Name 取首字,Tone 走语义色;Stack 为叠放组)。
type UIAvatarSpec struct {
Name string `json:"name,omitempty"`
Sub string `json:"sub,omitempty"` // 名字旁的小注(角色/状态)
Tone string `json:"tone,omitempty"` // ok/warn/danger/info/留空=品牌色
Stack []UIAvatarSpec `json:"stack,omitempty"` // 叠放头像组(多成员)
}
// UIProgress:0–1 归一进度或 n/m 计数(Value=Done/Total 任一形式,前端按 <1 判定)。
type UIProgressSpec struct {
Label string `json:"label,omitempty"`
Value float64 `json:"value"`
Tone string `json:"tone,omitempty"`
}
// UICompare:左右对比布局;两侧各带语义色调(如左=基线 danger、右=新内容 ok)。
type UICompareSide struct {
Title string `json:"title,omitempty"`
Tone string `json:"tone,omitempty"`
Nodes []UINode `json:"nodes,omitempty"`
}
type UICompareSpec struct {
Left UICompareSide `json:"left"`
Right UICompareSide `json:"right"`
}
// UITreeNode:树节点;Badge 为角标文本(如"多挂载"),Count 为子孙计数,
// onSelect 语义由宿主按 Tree 用途路由(命令或工作区定位)。
type UITreeNode struct {
ID string `json:"id"`
Label string `json:"label"`
Tone string `json:"tone,omitempty"` // 状态灯
Badge string `json:"badge,omitempty"`
Count int `json:"count,omitempty"`
Selected bool `json:"selected,omitempty"`
Children []UITreeNode `json:"children,omitempty"`
}
type UITreeSpec struct {
Nodes []UITreeNode `json:"nodes"`
}
type UITableColumn struct {
Key string `json:"key"`
Label string `json:"label"`
}
type UITableRow struct {
ID string `json:"id,omitempty"`
Cells [][2]string `json:"cells"` // 与 Columns.Key 对应的有序单元格
Actions []UIAction `json:"actions,omitempty"` // 行级操作(走命令总线)
}
type UITableSpec struct {
Columns []UITableColumn `json:"columns"`
Rows []UITableRow `json:"rows"`
}
type UIStep struct {
Label string `json:"label"`
Status string `json:"status,omitempty"` // pending | active | done | failed
Tone string `json:"tone,omitempty"`
}
type UIStepsSpec struct {
Current int `json:"current"` // 当前步下标(0 起)
Steps []UIStep `json:"steps"`
}
type UITab struct {
ID string `json:"id"`
Label string `json:"label"`
Nodes []UINode `json:"nodes,omitempty"`
}
type UITabsSpec struct {
Active string `json:"active,omitempty"` // 默认选中页签 ID
Tabs []UITab `json:"tabs"`
}
type UITimelineItem struct {
Time string `json:"time,omitempty"` // 展示用时间文本
Title string `json:"title"`
Tone string `json:"tone,omitempty"`
Markdown string `json:"markdown,omitempty"` // 条目正文
Ref string `json:"ref,omitempty"` // 引用标识(切片/版本/操作者)
}
type UITimelineSpec struct {
Items []UITimelineItem `json:"items"`
}
type UIField struct {
Key string `json:"key"`
Label string `json:"label"`
Type string `json:"type"` // text | textarea | number | boolean | select
Options []string `json:"options,omitempty"`
Required bool `json:"required,omitempty"`
Placeholder string `json:"placeholder,omitempty"`
Help string `json:"help,omitempty"`
Default string `json:"default,omitempty"`
}
type UIAction struct {
ID string `json:"id"`
Label string `json:"label"`
Style string `json:"style,omitempty"` // primary | default | danger
Command string `json:"command,omitempty"` // 绑定命令总线命令 id;空则降级为发消息
}
type UIChart struct {
Kind string `json:"kind"` // bar | line
Labels []string `json:"labels"`
Series []float64 `json:"series"`
}