# VeADK Studio AI 开发规范

本文档是 VeADK Studio 前端及其配套后端接口的 AI 开发规范。AI 在新增功能、
修复问题、生成代码或审查 PR 时，必须遵守本文档。

规范中的关键词含义如下：

- **必须**：不可省略；不满足时不得合入。
- **应该**：默认遵守；偏离时必须在 PR 中说明理由。
- **禁止**：不得引入；已有代码在相关功能被修改时应逐步迁移。

## 参考 Skill 与优先级

涉及页面、组件、交互、样式、图标或品牌资产的任务，AI 必须先完整阅读：

- [`frontend-design`](../.agents/skills/frontend-design/SKILL.md)：用于建立明确的设计
  方向、保持视觉一致性，并检查排版、颜色、空间、动效和完成度。

使用该 Skill 时遵循以下优先级：

1. 用户当前需求和安全约束。
2. 本 `SPEC.md` 中针对 VeADK Studio 的强制规范。
3. `frontend-design` Skill 提供的通用设计方法。
4. 当前代码中的既有实现惯例。

`frontend-design` 用于提高设计判断和实现质量，不代表可以重新定义产品风格。与本文
冲突时，必须以本文为准。例如，VeADK Studio 继续使用当前系统字体栈和克制的企业
工作台视觉，不应为了追求差异化擅自引入展示字体、夸张构图或高强度装饰。

如果任务不涉及视觉或交互，不应为了使用 Skill 扩大改动范围。

## 1. 产品与设计方向

VeADK Studio 是面向 Agent 开发、调试和部署的企业级工作台，不是营销站点，也
不是通用聊天模板。界面必须体现以下特征：

- 克制、安静、精确，优先保证信息层级和操作效率。
- 以浅色中性灰画布、白色面板、细边框和近黑文字为主。
- 通过间距、字重、分组和轻量状态色表达层级，不依赖大面积高饱和色。
- 交互必须让用户明确知道当前 Agent、Session、Runtime、区域、构建阶段和错误
  原因。
- 不得使用紫色渐变、霓虹发光、玻璃拟态、大面积插画等与当前工作台风格不一致
  的装饰。
- 不得为了“更像 AI 产品”随意添加星星、魔法棒、机器人头像或无语义动画。

任何视觉改动都应先回答三个问题：

1. 它帮助用户完成什么任务？
2. 它是否与当前页面的信息密度和层级一致？
3. 去掉装饰后，操作含义是否仍然清楚？

## 2. 代码改动原则

### 2.1 最小且可验证

- 只修改完成当前需求所必需的文件和代码。
- 禁止顺手重构无关模块、统一无关格式或删除既有代码。
- 优先复用现有数据结构、CSS 变量、组件和 API 客户端。
- 不为单一场景提前设计通用框架。
- 新增依赖前必须证明现有能力无法完成需求，并说明体积、维护和安全影响。
- 修复问题时必须先明确可复现条件，再增加对应测试。

### 2.2 快速失败

- 输入、配置或服务端响应不满足约定时，应在最接近边界的位置明确失败。
- 禁止无针对性的 `try/catch`、吞掉异常或静默切换到另一种行为。
- 只捕获能够恢复、补充上下文或转换为用户可理解错误的异常。
- 不得把网络错误、鉴权错误或配置错误伪装成“无数据”。

### 2.3 类型与模块

- 使用 TypeScript、React 函数组件和命名导出。
- 禁止新增无理由的 `any`、双重类型断言或绕过类型检查的注释。
- 共享类型放在领域文件中，不创建含义模糊的全局 `utils.ts`。
- 纯转换逻辑应提取为无副作用函数，以便独立测试。
- 组件内部状态应归属最小必要范围；跨页面任务状态必须放在能持续存在的上层。
- 异步任务必须处理取消、组件卸载和过期响应，避免旧请求覆盖新状态。
- 定时器、临时调试 Runtime、对象 URL 和事件监听器必须清理。

## 3. 前端视觉规范

### 3.1 颜色

必须优先使用 `src/styles.css` 中的语义变量：

```css
hsl(var(--background))
hsl(var(--foreground))
hsl(var(--panel))
hsl(var(--canvas))
hsl(var(--muted))
hsl(var(--muted-foreground))
hsl(var(--border))
hsl(var(--primary))
hsl(var(--destructive))
```

- 禁止为普通文字、边框、背景和 Hover 状态新增零散十六进制颜色。
- 成功、警告、错误等状态色可以使用明确的 HSL 值，但同一语义必须保持一致。
- 颜色不能成为唯一的状态提示；必须同时提供文字、图标或形状差异。
- 新增主题变量时必须说明语义，禁止使用 `--gray-1`、`--blue-new` 等视觉命名。

### 3.2 字体与文字

- 继续使用当前中英文系统字体栈，不得为单个页面引入网络字体。
- 正文通常为 `12.5px` 至 `14px`，页面标题和关键标题按现有组件层级递增。
- 通过 `500` 至 `650` 的字重建立层级，避免全页粗体。
- 文案应简短、直接、使用用户语言；不得直接展示内部异常类名代替解释。
- Agent、Runtime、Session、API、YAML 等产品术语应保持统一写法。
- 超长名称必须使用省略、换行或独立滚动区，不得撑破布局。

### 3.3 间距、圆角与边框

- 基础间距以 `4px` 倍数为主，常用间距为 `8px`、`12px`、`16px`、`24px`。
- 普通控件圆角通常为 `6px` 至 `8px`，浮层和主面板通常为 `12px`。
- 普通分隔使用一像素 `--border`，避免多层重边框。
- 阴影只用于真正浮在内容之上的菜单、抽屉和对话框。
- 同一行中的按钮、输入框和选择器必须具有一致的高度和视觉基线。

### 3.4 布局与滚动

- 应用保持固定视口工作台结构，页面自身不得出现无控制的 Body 滚动。
- Flex 或 Grid 滚动子项必须正确设置 `min-width: 0` 和 `min-height: 0`。
- Sidebar、表单、代码区、调试区和历史记录应拥有独立且有边界的滚动区域。
- 主要内容宽度应保持可读，不得让表单在宽屏上无限拉伸。
- 窄桌面宽度下，应把结构树、配置区和调试区有序堆叠，而不是压缩到不可用。
- 加载、校验提示和行内操作应预留空间，避免出现后导致输入框或列表跳动。
- Hover 才显示的操作应保留布局槽位，避免文字宽度变化。

### 3.5 动效

- 动效只用于解释状态变化、层级进入或操作反馈。
- 常规过渡时长为 `120ms` 至 `220ms`，优先使用 ease-out 或当前缓动曲线。
- 禁止无限循环装饰动画；加载 Spinner 和运行状态脉冲除外。
- 新增动效必须支持 `prefers-reduced-motion: reduce`。
- 动效不得阻塞点击、输入、导航或错误阅读。

## 4. 图标规范

### 4.1 产品图标必须自绘

- 所有新增或改造的产品图标必须是仓库内自绘 SVG。
- 禁止直接使用 Lucide、Font Awesome、Material Icons、Iconfont 或其他通用图标库
  作为最终产品图标。
- 禁止使用 Emoji、Unicode 符号或文字字符冒充图标。
- 禁止从网络远程加载图标，也不得提交来源和授权不明确的 SVG。
- 已有通用图标库代码可以渐进迁移；修改某个功能时，应同时替换该功能涉及的
  通用图标，避免继续扩大依赖范围。

### 4.2 绘制要求

产品图标应实现为独立 React 组件，通用图标放在 `src/ui/icons/`，只在单个功能使用
的图标可以放在功能目录。推荐接口：

```tsx
import type { SVGProps } from "react";

export function ExampleIcon(props: SVGProps<SVGSVGElement>) {
  return (
    <svg
      viewBox="0 0 24 24"
      fill="none"
      stroke="currentColor"
      strokeWidth="1.75"
      strokeLinecap="round"
      strokeLinejoin="round"
      aria-hidden="true"
      {...props}
    >
      <path d="..." />
    </svg>
  );
}
```

- 默认画布为 `24 × 24`，视觉主体应留出一致安全边距。
- 线性图标默认使用 `currentColor`、`1.75` 至 `1.8` 线宽、圆角端点和连接。
- 同一组图标必须具有一致的线宽、留白、转角和视觉重量。
- 图形必须表达具体功能，不得只做字面装饰。
- SVG 路径应保持简洁，不得嵌入编辑器元数据、位图或 Base64。
- 图标颜色由容器状态控制，图标组件内部不得硬编码普通状态颜色。
- 常规图标尺寸使用现有 `.icon` 的 `16px` 基准；导航或关键入口可以按现有样式
  放大到 `18px` 至 `20px`。

### 4.3 可访问性

- 纯装饰图标必须设置 `aria-hidden="true"`。
- 只有图标没有文字的按钮必须提供准确的 `aria-label` 和必要的 `title`。
- 有可见文字的按钮不重复朗读图标名称。
- 禁止用颜色或图标替代必要的错误文字和状态文字。

### 4.4 Logo 与站点品牌

- Logo 属于用户品牌资产，不受“必须自绘产品图标”规则限制。
- 用户上传的任意尺寸 Logo 必须缩放到当前 `20px × 20px` 视觉框，使用
  `object-fit: contain`，不得改变 Sidebar 或登录页布局。
- Sidebar、登录页、浏览器 favicon 必须使用同一 Logo 来源。
- 浏览器标题、登录页标题和 Sidebar 标题必须使用同一站点标题。
- 站点标题最多六个字符；默认品牌回退必须稳定。

## 5. 组件与交互规范

### 5.1 组件设计

- 先复用现有按钮、卡片、菜单、错误信息和表单模式，再新增组件。
- 同一组件不得同时承担数据请求、复杂转换和大段视觉渲染；职责过大时按领域拆分。
- 列表必须使用稳定业务 Key，禁止用数组下标表示可增删或可排序项目。
- 弹层必须具有明确层级、关闭方式、焦点行为和点击外部处理。
- 禁用控件必须有不可点击状态；仍可操作的加载按钮必须显示进行中状态。
- 删除、取消部署、清空配置等破坏性操作必须要求用户确认。

### 5.2 输入与中文输入法

- 文本输入必须正确处理 IME Composition。
- Composition 期间按 Enter 不得提交；Safari 的兼容键值也必须覆盖。
- 普通 Enter、Shift+Enter、Tab、Escape 等行为必须在组件和测试中明确。
- 发送成功后输入框、附件和 Invocation 状态必须同步清理，不得留下视觉残留。
- 文件输入处理完成后应清空 input value，允许用户再次选择同一文件。

### 5.3 页面状态

- 登录成功后默认进入“新会话”主页，除非用户明确导航到其他页面。
- 新会话空状态保持简洁，不显示 Session ID 和免责声明等对话后元信息。
- 正式会话开始后再显示 Session、回答提示和 Trace 等上下文信息。
- 页面切换不能丢失仍在执行的部署任务；任务状态必须在全局区域持续可见。
- 加载、空数据、错误、无权限和成功状态必须分别设计，不得混为一类。

### 5.4 可访问性与键盘

- 所有交互元素必须使用正确的 `button`、`input`、`nav` 等语义标签。
- 所有主要操作必须能够通过键盘完成。
- 自定义列表选择应使用合适的 `role`、`aria-selected` 和可见焦点。
- 动态错误和校验信息应使用 `role="alert"` 或 `aria-live`。
- 点击区域不得小于当前同级控件的可用尺寸，图标按钮应保持稳定方形区域。

## 6. Agent 创建与配置规范

### 6.1 配置必须显式

- 飞书、知识库、短期记忆、长期记忆和观测参数必须显示在各自功能区域。
- 禁止用户打开功能后，系统在不可见位置静默添加环境变量。
- 用户填写的值必须同步显示在部署页的环境变量摘要中。
- 展示值、生成代码和实际 Runtime 环境变量必须来自同一份 Draft 状态。
- 影响生成代码、依赖或入口参数的开关发生变化时，必须重新生成项目。

### 6.2 环境变量与密钥

- 配置 UI 负责收集领域参数，部署层负责转换为 VeADK Runtime 环境变量。
- 密钥不得写入生成源码、README、YAML、浏览器 Local Storage、日志或错误详情。
- `.env.example` 只能包含键名、说明和无效占位符。
- 密钥输入默认应遮罩；仅在用户主动操作时临时显示。
- 环境变量名称必须在前后端共同校验，禁止任意非法键名进入 Runtime。
- 观测 Exporter 被选中时，必须同时生成其参数和对应 `ENABLE_*` 开关。

### 6.3 生成代码

- 生成结果必须确定、完整并可运行，不得依赖用户手工补齐隐藏代码。
- 根 Agent 和任意层级的 LLM、Sequential、Parallel、Loop、A2A 子 Agent 必须递归
  生成并保持拓扑关系。
- Agent 名称必须符合 Google ADK 规则，并在整个嵌套树中唯一。
- Python 文件必须能通过语法检查、Ruff 和 Pyright。
- 依赖、入口参数和 `.env.example` 必须与启用组件保持一致。
- 飞书启用时，入口必须显式启用 Feishu Channel，并包含所需扩展依赖。
- 生成器新增能力时必须同时更新对应文档和 `frontend/README.md`。

## 7. Session、Runtime 与网络规范

- Session 创建、查询、删除和 `/run_sse` 必须使用同一组 `app_name`、`user_id` 和
  `session_id`。
- 如果由前端生成 Session ID，应使用 `crypto.randomUUID()`；不得使用时间戳、递增
  数字、用户名或其他可预测值。
- 前端生成 Session ID 不能替代服务端持久化或 FaaS 实例亲和。
- 多实例 Runtime 使用 in-memory 或 SQLite Session 时，必须提示可能因请求落到不同
  实例而返回 404。
- 需要跨实例可靠恢复时，必须使用数据库持久化 Session；实例亲和只能作为优化，
  不能作为数据可靠性保证。
- 如果平台使用 `X-FaaS-Instance-Name`，该 Header 只能存在于 APIG 和 FaaS Gateway
  之间，浏览器不得直接控制实例名称。
- Runtime、区域、Endpoint 和鉴权类型必须显式显示，不能依赖隐含全局状态。
- CORS、Origin 和代理规则必须显式配置；禁止用放开所有 Origin 的方式规避本地问题。

## 8. 错误、日志与可诊断性

- 禁止只向用户展示 `BUILD_FAILED`、`Internal Server Error` 或“连接中断”。
- 错误必须尽可能包含失败阶段、可执行原因和下一步建议。
- 云构建错误应显示经过脱敏的关键日志片段，并提供展开、复制和重试操作。
- 非 JSON 响应必须说明状态码和 Content-Type，提示检查代理或网关配置。
- SSE 必须有明确终止帧；连接提前关闭时应区分服务端失败、用户取消和网络中断。
- `run_sse` 404 应提示检查 Session 是否位于另一个实例，以及是否使用持久化后端。
- 错误展示不得泄漏 AK/SK、API Key、JWT、Cookie、飞书 Secret 或完整环境变量。
- 日志脱敏必须发生在进入 UI、持久化文件或 CI 输出之前。
- 可恢复错误必须提供重试；不可恢复错误必须指出需要修改的配置。

## 9. API 与异步请求规范

- API 客户端统一放在 `src/adk/`，组件不得散落拼接同一类 Endpoint。
- 请求和响应必须有明确 TypeScript 类型。
- 非流式 API 使用统一超时；文件传输使用独立较长超时。
- SSE、调试和部署流保持长连接，直到服务端完成或用户明确取消。
- 有任务 ID 的部署必须支持取消，并清理已创建的临时 Runtime。
- 请求失败时保留服务端可诊断信息，但必须先脱敏。
- 不得因为请求失败而静默切换登录模式、Agent 来源或存储后端。
- 用户快速切换 Agent、页面或配置时，旧请求结果不得覆盖当前选择。

## 10. A2UI 规范

- 每个 A2UI 组件放在 `src/a2ui/components/<Name>/` 并通过 Registry 注册。
- 前端 Renderer 与后端 Catalog 必须同步更新。
- 未知组件必须安全降级，不得导致整个会话页面崩溃。
- A2UI 组件仍须遵守本文档的图标、颜色、可访问性和错误规范。
- Agent 提供的文本、URL 和富内容必须按现有安全策略渲染，禁止直接信任 HTML。

## 11. 测试与交付门槛

### 11.1 前端改动

提交前必须运行：

```bash
cd frontend
npm test
npm run build
```

- Bug 修复必须包含能够复现原问题的测试。
- 交互测试必须覆盖正常、加载、错误、禁用和重试状态。
- 输入框改动必须覆盖 IME、键盘和重复提交。
- 配置改动必须验证 UI 值、生成代码、环境变量和部署 Payload 一致。
- 品牌改动必须验证 Sidebar、登录页、favicon 和 `document.title`。
- 构建会更新 `veadk/webui`；发布相关改动必须提交匹配的构建产物。

### 11.2 Python 或代码生成改动

必须运行目标测试，并对所有修改的 Python 文件执行：

```bash
uv run ruff check <changed-python-files>
uv run pyright <changed-python-files>
```

- Markdown 文件必须通过项目使用的 Markdown/MDX 检查。
- 提交前必须运行密钥扫描，确认源码、测试快照和构建产物均无凭据。
- 高风险部署链路应执行生成项目启动测试；涉及云平台时，应至少验证构建错误能够
  被完整、脱敏地返回。
- 不得以“本地看起来正常”替代自动化测试。

## 12. AI 执行流程

AI 每次开发任务必须按以下顺序执行：

1. 阅读相关组件、类型、样式、测试和后端接口。
2. 明确需求边界、假设和可验证成功标准。
3. 选择最小实现，说明会影响的代码生成、Runtime 或安全边界。
4. 先补充复现测试或契约测试，再实现功能。
5. 使用现有视觉变量和组件完成 UI，产品图标必须自绘。
6. 验证加载、错误、空状态、取消、重试、窄窗口和键盘行为。
7. 运行测试、构建、Ruff、Pyright、文档检查和密钥扫描。
8. 检查 Diff，删除仅由本次改动产生的无用代码，不处理无关历史问题。
9. 更新 `frontend/README.md` 和相关用户文档。
10. 在 PR 中列出实际验证结果和仍未覆盖的限制，禁止夸大完成度。

## 13. PR 审查清单

- [ ] 改动与需求直接相关，没有无关重构。
- [ ] 所有新增产品图标均为仓库内自绘 SVG。
- [ ] 没有新增通用图标库用法、Emoji 图标或远程图标。
- [ ] 使用现有颜色、间距、圆角和状态模式。
- [ ] 键盘、IME、焦点和无障碍属性完整。
- [ ] 加载、空状态、错误、重试和取消路径完整。
- [ ] 配置在功能区域与环境变量摘要中均可见。
- [ ] 密钥只进入 Runtime 环境，不进入源码、日志或浏览器持久化。
- [ ] 生成代码、依赖和环境变量保持一致。
- [ ] 多实例 Session 行为和持久化要求已明确。
- [ ] 新增行为有测试，前端测试和生产构建通过。
- [ ] 修改的 Python 文件通过 Ruff 和 Pyright。
- [ ] 文档、构建产物和密钥扫描均已更新并通过。
