# 本地交互式回答 聊天保留 AI SDK `UIMessage`、AI Elements 与现有 Agent 后端,新增 `@json-render/core` / `@json-render/react` 的本地注册组件。 组件代码随前端构建发布,无 ChatKit iframe、domain key 或 Vercel/OpenAI 托管 UI 请求。模型仍使用 Agent 的既有配置与工具调用能力。 ## 可用内容与交互 `Stack`、`Section`、`Text`、`Metric`、`Table`、`Chart`、`Evidence`、 `MapLocation`、`FollowUpForm` 共九种组件。图表可切换折线、柱状和数据表; 证据可折叠并标注来源;地图定位通过现有控制器执行;表单从空值开始, 由用户主动提交,提交形成普通用户消息。业务证据是否保存以 Agent 实际工具结果为准。 Agent 通过 `present_answer` 发布完整的局部界面块,可在两块之间继续输出文字。 消息顺序为文字、`data-answer_ui`、后续文字与最终报告。同一轮内相同 `block_id` 更新原块;下一轮不会修改上一轮回答。 这是按内容块逐步出现的界面,不是逐 token 编译 JSX 或每个 JSON 属性都立即显示。 结构化消息与普通聊天共用持久化、历史与断线恢复通道。 生成期间展开显示过程;`final_answer` 到达后,仅展开最后报告的完整文字与 `ui_block_ids` 明确引用的已发布组件,其余文字、界面与工具轨迹默认折叠在 “查看处理过程”中。报告组件按引用顺序排列,同一组件不会同时作为报告和过程 挂载,避免重复表单。未被报告引用的过程界面只供回看。 已发布交互界面的普通/协作聊天在最终答复完成、且没有待完成工具时停止本轮原生 生成,防止最终报告之后反复自动修改界面。该收尾不标记后台调查任务完成; 后台执行继续等待其原有运行生命周期与 Server 完成/失败接口。 后台调查执行继续走任务报告与任务展示通道,聊天界面块不构成业务完成或浏览器回执。 ## 扩展组件 1. 在 `src/features/agent/answer-ui/catalog.ts` 增加严格的 Zod 参数定义、用途描述与必要的数据上限。 2. 在 `answer-ui-view.tsx` 注册 React 组件。需要工作台交互时通过 Agent 公共 API 的回调接入,保持依赖方向。 3. 从本仓库运行 `pnpm export:answer-ui-contract`,更新相邻 Agent 仓库的 `src/chat/answer-ui-catalog.json`。组件目录是唯一参数定义源,生成文件需随两边一起交付。 4. 如新组件存在跨字段约束,同时更新两端的协议校验并加边界和交互测试。 导出脚本接受可选目标文件: ```bash node scripts/export-answer-ui-contract.mjs /path/to/agent/src/chat/answer-ui-catalog.json ``` 前端沿用 Zod 3,json-render 0.21 两个包通过作用域 override 使用相同 schema 运行时;实际组件渲染和参数校验已有聚焦测试。升级 json-render 时必须保留这组 兼容性测试,不能只根据包版本判断可用。Agent 原生插件仍使用其 Zod 4 工具边界, 执行后再按生成的 JSON Schema 校验组件参数。 ## 校验边界 两端拒绝未知组件、额外属性、任意脚本/事件定义、缺失引用、循环、重复或游离节点。 每块最多 48 节点、深度 12、约 100 KB,图表必须对齐且数值有限;表格每行与列数 一致,表单字段名唯一。组件只消费明确的 props,没有动态代码、网络 URL 或任意动作 DSL。 无法解析的历史内容显示该块的 `fallback_text`。 ## 验证 ```bash pnpm lint pnpm typecheck pnpm test src/features/agent/answer-ui src/features/workbench/hooks/agent-session-message-state.test.ts pnpm test:browser tests/browser/agent-answer-ui.e2e.ts tests/browser/agent-start-page.e2e.ts pnpm build ``` Agent 仓库: ```bash bun run check bun test tests/chat/answer-stream-projection.test.ts tests/chat/answer-ui.test.ts tests/routes/chatStream.test.ts tests/routes/taskCollaboration.test.ts tests/runtime/opencode.test.ts bun run tests/integration/answer-ui-smoke.ts ``` 原生 smoke 使用独立临时数据库,不发模型推理请求。浏览器用例用明确标注的演练 事件验证组件、更新、历史恢复、键盘展开证据、表单提交和 320/375px 布局,不能当作 真实模型已正确选择组件或现场资料已核验的证明。 前端与 Agent 需一起更新,Agent 进程需重新加载原生插件。无需新增环境变量、 domain key 或数据库迁移。当前开发实例通过现有监听机制重新加载;既有聊天与调查工作进程保留。 ## 真实模型验收(显式启用) 以下浏览器用例直接连接本机 Agent,输入均为明确的演练资料。工作台地图与项目 读取使用测试数据,聊天、模型工具调用、流式 UI、聊天持久化与表单回传使用真实 服务。每次创建独立验收会话,结束后仅删除该会话,不删除既有用户记录。此用例 会发送模型请求,默认浏览器测试不执行它。 ```bash TJWATER_ANSWER_UI_REAL_AGENT_URL=http://127.0.0.1:18787 \ TJWATER_ANSWER_UI_REAL_MODEL_LABEL=专家 \ pnpm test:browser tests/browser/agent-answer-ui-real.e2e.ts --workers=1 ``` 先在 Agent 仓库启动隔离实例,可指定独立 INTEGRATION_DATA_DIR 保留联调数据。 可省略模型标签来使用默认模型。该用例不是生产 OAuth 登录或真实供水业务核验。 Vite 统一解析 React/React DOM,Playwright 按端口使用独立的依赖缓存,避免同时 运行的开发服务将旧临时目录的 React 预构建写回测试缓存。 消息入口为 `POST /api/v1/responses`,采用 Responses 文本输入、Response 输出和标准 SSE 生命周期。前端 `ResponsesChatTransport` 将网络事件转换为已有 UIMessage 渲染数据;审批、凭据续期、地图动作及 answer-ui 走 `tjwater.*` 扩展事件,不将 AI SDK 的 UIMessage 流作为网络协议。会话、模型及动作回执等接口统一使用 `/api/v1` 前缀,原 `/agent/chat` 路径已移除;Agent 服务和现有会话数据保留。