refactor: 移除前端 Mock API,新增共享组件,优化认证流程

- 删除 mock_api_client、mock_calendar_service、mock_history_service
- 新增 fixed_length_code_input、link_button、message_composer 共享组件
- 优化登录/注册/密码重置页面使用新组件
- 简化 injection.dart 移除 mock 分支
- 更新 env.dart 配置(BACKEND_URL 替换 API_URL)
- 后端 agentscope 工具和测试更新
- 重构 AGENTS.md 文档结构
- 新增 deploy/ 目录和 protocol 文档
This commit is contained in:
qzl
2026-03-12 16:41:45 +08:00
parent d7fbb74bf8
commit 01c36eb32e
70 changed files with 5138 additions and 5829 deletions
+466
View File
@@ -0,0 +1,466 @@
# UI Schema Protocol
> **NOTE**: This document is the single source of truth. All implementations must follow this specification.
## Overview
A generic UI schema for rendering tool/agent execution results. Designed for AI Agent / Tool ecosystem with extensibility.
## Version
- **Current**: `1.0`
- **Status**: Frozen (no new node types)
## Architecture
```
┌─────────────────────────────────────────────────────────────┐
│ UiSchemaDocument (root) │
│ - version / schemaType / status / docId │
│ - meta (protocol-level metadata) │
│ - nodes (array of UiNode) │
├─────────────────────────────────────────────────────────────┤
│ Field Layers: │
│ 1. Public fields (all renderers must handle) │
│ id / type / title / description / icon / status / │
│ timestamp / actions │
│ 2. meta (protocol-level, not rendered) │
│ requestId / toolId / traceId / userId │
│ 3. extensions (tool私有扩展, renderer透传) │
└─────────────────────────────────────────────────────────────┘
```
---
## Data Types
### SchemaType
```typescript
type SchemaType = 'tool_result' | 'agent_response' | 'notification';
```
### UiStatus
```typescript
type UiStatus = 'info' | 'success' | 'warning' | 'error' | 'pending';
```
### IconSource
```typescript
type IconSource = 'icon' | 'emoji' | 'url';
```
### ActionType
```typescript
type ActionType = 'navigation' | 'url' | 'event' | 'tool' | 'copy' | 'payload';
```
---
## Root Structure
```typescript
interface UiSchemaDocument {
// Protocol identifier
version: string; // "1.0"
schemaType: SchemaType; // tool_result | agent_response | notification
// Document metadata
docId?: string; // For local refresh / diff / analytics
timestamp?: string; // ISO 8601
locale?: string; // "zh-CN"
// Unified status
status: UiStatus;
// Render control
renderer?: {
renderer?: string; // Dedicated renderer name
theme?: 'default' | 'dark' | 'light';
};
// Protocol-level metadata (not rendered)
meta?: {
requestId?: string;
toolId?: string;
traceId?: string;
userId?: string;
[key: string]: any;
};
// Root nodes
nodes: UiNode[];
}
```
---
## Node Types (v1 Whitelist)
```
✅ Supported in v1:
- card 卡片
- list 列表
- table 表格
- text 文本/Markdown
- kv 键值对
- operation 操作结果
- error 错误提示
- container 容器
❌ Not supported in v1 (reserved for v2):
- chart / metric / image / video / tabs / accordion / form
```
---
## Common Node Fields
All nodes share these fields:
```typescript
interface UiBaseNode {
id?: string; // For local refresh / action targeting
type: string; // Node type identifier
}
interface UiTitledNode extends UiBaseNode {
title?: string;
description?: string;
icon?: UiIcon;
status?: UiStatus;
timestamp?: string;
}
interface UiActionableNode extends UiTitledNode {
actions?: UiAction[];
}
interface UiExtendableNode extends UiActionableNode {
extensions?: Record<string, any>; // Tool私有扩展, 通用renderer透传
}
```
---
## Node Definitions
### 1. Card Node
```typescript
interface UiCardNode extends UiExtendableNode {
type: 'card';
children?: UiNode[]; // Nested nodes
footer?: UiTextNode;
}
```
### 2. List Node
```typescript
interface UiListNode extends UiExtendableNode {
type: 'list';
items: ListItem[];
pagination?: {
page: number;
pageSize: number;
total: number;
hasMore: boolean;
};
emptyText?: string;
}
interface ListItem {
id: string;
title: string;
subtitle?: string;
description?: string;
icon?: UiIcon;
badge?: { label: string; variant?: 'default' | 'success' | 'warning' | 'error' | 'info' };
metadata?: Record<string, any>;
actions?: UiAction[];
}
```
### 3. Table Node
```typescript
interface UiTableNode extends UiExtendableNode {
type: 'table';
columns: TableColumn[];
rows: TableRow[];
pagination?: Pagination;
}
interface TableColumn {
key: string;
label: string;
width?: string;
align?: 'left' | 'center' | 'right';
}
interface TableRow {
id: string;
cells: Record<string, any>;
metadata?: Record<string, any>;
actions?: UiAction[];
}
```
### 4. Text Node
```typescript
interface UiTextNode extends UiBaseNode {
type: 'text';
content: string;
format?: 'plain' | 'markdown';
icon?: UiIcon;
actions?: UiAction[];
}
```
### 5. Key-Value Node
```typescript
interface UiKvNode extends UiExtendableNode {
type: 'kv';
pairs: KeyValuePair[];
layout?: 'vertical' | 'horizontal' | 'grid';
}
interface KeyValuePair {
key: string;
label?: string;
value: string | number | boolean;
copyable?: boolean;
}
```
### 6. Operation Node
```typescript
interface UiOperationNode extends UiExtendableNode {
type: 'operation';
operation: 'create' | 'update' | 'delete' | 'execute';
result: 'success' | 'failure' | 'partial';
message?: string;
affectedCount?: number;
details?: UiNode;
rollback?: UiAction;
}
```
### 7. Error Node
```typescript
interface UiErrorNode extends UiBaseNode {
type: 'error';
title?: string;
icon?: UiIcon;
errorCode: string;
message: string;
details?: string;
stack?: string;
retryable: boolean;
suggestions?: string[];
retry?: UiAction;
support?: UiAction;
actions?: UiAction[];
}
```
### 8. Container Node
```typescript
interface UiContainerNode extends UiBaseNode {
type: 'container';
direction: 'vertical' | 'horizontal';
gap?: number;
children: UiNode[];
actions?: UiAction[];
}
```
---
## Action Structure
```typescript
interface UiAction {
id: string;
label: string;
icon?: UiIcon;
style?: 'primary' | 'secondary' | 'ghost' | 'danger';
disabled?: boolean;
action: ActionSpec;
confirm?: {
title?: string;
message?: string;
confirmLabel?: string;
cancelLabel?: string;
};
}
type ActionSpec =
| { type: 'navigation'; path: string; params?: Record<string, any> }
| { type: 'url'; url: string; target?: '_self' | '_blank' }
| { type: 'event'; event: string; payload?: Record<string, any> }
| { type: 'tool'; toolId: string; params?: Record<string, any> }
| { type: 'copy'; content: string; successMessage?: string }
| { type: 'payload'; payload: Record<string, any>; submitTo?: string };
```
---
## Icon Structure
```typescript
interface UiIcon {
source: IconSource; // 'icon' | 'emoji' | 'url'
value: string; // icon name / emoji / URL
color?: string; // "#FF0000"
size?: number; // pixels
}
```
---
## Usage Rules
### operation vs error
| Scenario | Node Type |
|----------|-----------|
| Tool execution failed, system exception | `UiErrorNode` |
| Business operation result (CRUD) | `UiOperationNode` |
| Network error / permission denied | `UiErrorNode` |
### extensions Usage Constraints
1. ❌ NO: Any rendering-related style / text / layout
2. ❌ NO: Any fields other renderers need to read
3. ✅ YES: Business identifiers (eventId, orderId)
4. ✅ YES: Dedicated renderer private config
5. ✅ YES: Analytics / logging context data
6. ✅ YES: Data that generic renderer doesn't care about
---
## JSON Examples
### Example 1: Success Card
```json
{
"version": "1.0",
"schemaType": "tool_result",
"docId": "doc_evt_001",
"timestamp": "2026-03-12T10:30:00Z",
"status": "success",
"renderer": { "renderer": "calendar" },
"meta": { "requestId": "req_abc", "toolId": "calendar.create_event" },
"nodes": [
{
"id": "node_card_1",
"type": "card",
"title": "日程已创建",
"description": "会议日程创建成功",
"icon": { "source": "icon", "value": "event_available" },
"extensions": { "eventId": "evt_abc123", "color": "#3B82F6" },
"children": [
{
"type": "kv",
"pairs": [
{ "key": "title", "label": "主题", "value": "Q1 规划会议" },
{ "key": "time", "label": "时间", "value": "2026-03-15 14:00" }
]
}
],
"actions": [
{
"id": "action_view",
"label": "查看详情",
"style": "primary",
"action": { "type": "navigation", "path": "/calendar/evt_abc123" }
}
]
}
]
}
```
### Example 2: List Result
```json
{
"version": "1.0",
"schemaType": "tool_result",
"status": "success",
"meta": { "toolId": "search.documents" },
"nodes": [
{ "type": "text", "content": "找到 **3** 个相关文档" },
{
"id": "node_list_1",
"type": "list",
"items": [
{
"id": "item_1",
"title": "API 设计规范",
"subtitle": "v2.1",
"icon": { "source": "emoji", "value": "📄" },
"actions": [
{ "id": "a1", "label": "查看", "action": { "type": "url", "url": "/docs/api" } }
]
}
],
"pagination": { "page": 1, "pageSize": 10, "total": 3, "hasMore": false }
}
]
}
```
### Example 3: Error Result
```json
{
"version": "1.0",
"schemaType": "tool_result",
"status": "error",
"meta": { "toolId": "user.delete" },
"nodes": [
{
"id": "node_error_1",
"type": "error",
"title": "删除用户失败",
"icon": { "source": "icon", "value": "error_outline" },
"errorCode": "PERMISSION_DENIED",
"message": "您没有权限执行此操作",
"details": "需要管理员权限",
"retryable": true,
"suggestions": ["联系管理员", "联系技术支持"],
"retry": {
"id": "action_retry",
"label": "重试",
"style": "primary",
"action": { "type": "tool", "toolId": "user.delete", "params": { "userId": "u1" } }
}
}
]
}
```
---
## Evolution (v2)
Reserved for future:
- Nested containers: `tabs`, `accordion`, `carousel`
- Data visualization: `chart`, `metric`, `progress`
- Rich media: `image`, `video`, `audio`, `file`
- Internationalization: `i18nKey` field
- Version migration: `deprecated` flag
- Offline support: `offline` flag