feat: expand intelligent investigation workspace
Generic Container CI/CD / test-build-publish (push) Successful in 1m52s
Frontend CI/CD / build-test-publish-and-deploy (push) Successful in 1m52s

This commit is contained in:
2026-10-30 17:30:19 +08:00
parent ddd03dbff6
commit c0e4231b83
223 changed files with 13155 additions and 5304 deletions
+46 -15
View File
@@ -26,7 +26,7 @@ Agent 相关弹窗、面板及菜单统一保持本地 shadcn/ui 设计,具体
| 人工参与 | 权限审批、问题回答和跳过、补充资料 | 对应回复内保留可操作表单,确认前不执行 |
| 分析结果 | 指标、表格、折线和柱状图、证据 | 回复中的交互内容,可搜索、排序、选点、筛选序列及已加载区间 |
| 展开阅读 | 聊天回答与正式报告进入主工作区 | 明确点击进入,保留唯一组件实例、筛选、表单草稿和阅读位置 |
| 内容追问 | 指标、数据点、表格行、证据 | 带来源的可删除引用;正式报告另带版本和轮次;确认后发送 |
| 数据浏览 | 指标、数据点、表格、证据 | 展示与本地查看;不提供行勾选、分析篮或组件追问 |
| 正式报告 | 当前结论、结论边界、证据、缺口、待办、审批与历史版本 | 固定事实区与可选交互分析模块组合 |
| 地图联动 | 定位实际要素、显示定位结果 | 对应内容内的明确按钮 |
| 回复工具 | 复制正文及交互摘要、朗读和选段朗读 | 回复底部低强调操作及文字选择入口 |
@@ -114,13 +114,13 @@ Agent 面板
└─ 输入区:引用 / 多行输入 / 权限、模型、语音、发送或停止
```
纯指标的双列 `Stack` 合并为紧凑摘要区,容器宽度达到 240px 即可并排;名称、原始数值、单位和来源完整保留,不用省略号截断。指标提问按钮放在名称旁,减少单独操作行。混合内容的双列仍使用 440px 断点。助手正文直接进入消息流,证据按需折叠,补充表单保留独立操作区;表面与间距统一引用样式设计指南。
纯指标的双列 `Stack` 合并为紧凑摘要区,容器宽度达到 240px 即可并排;名称、原始数值、单位和来源完整保留,不用省略号截断。指标仅展示名称、数值、单位和来源。混合内容的双列仍使用 440px 断点。助手正文直接进入消息流,证据按需折叠,补充表单保留独立操作区;表面与间距统一引用样式设计指南。
图表首先显示标题、视图切换、序列和趋势。范围选择默认收起,展开后可选择起止点及重置;收起只改变展示,不取消已选范围。序列按钮使用低强调色,图例颜色保留数据对应关系;至少一条序列可见。数据点的各序列值分行对齐,保留原始精度。
正式报告展开后采用连续文档排版,章节之间使用细分隔线。目录跟随阅读区滚动,包含实际存在的结论、分析、调查进展、待办、处置、缺口、脉络、依据、时间线和版本。目录使用导航语义,点击或键盘激活后立即滚动并将焦点交给目标章节;手机目录可横向滚动。接近文档末尾、目标无法滚至顶部时,保留主动选择的章节标记,直到用户再次滚动。该导航只改变阅读位置,不控制任务执行或审批。
空会话采用“简短引导、首次输入、推荐问题”的顺序,整组在 Agent 面板内横向居中,放在会话栏下方可用区域的中部。居中容器最多 600px,桌面内边距 24px,手机左右内边距 16px;短屏内容超过可用高度时从顶部排列并允许滚动。判断依据是当前会话有无消息,不取决于帐号是否保存其他历史会话。加载历史或已有任务状态、审批、结构化结果时保留正常阅读区,不覆盖为欢迎页。
空会话采用“简短引导、首次输入、推荐问题”的顺序,整组在 Agent 面板内横向居中,放在会话栏下方可用区域的中部。居中容器最多 600px,桌面内边距 24px,手机左右内边距 16px;短屏内容超过可用高度时从顶部排列并允许滚动。判断依据是当前会话有无消息,不取决于帐号是否保存其他历史会话。加载历史、引用任务或已有工具权限审批、结构化结果时保留正常阅读区,不覆盖为欢迎页。
输入文字区初始高度 64px,按内容增长至视口允许的高度。首次发送后同一个输入组件回到底部;新建空会话后恢复居中布局。使用 `motion/react` 的位置布局动画处理这两种状态,沿用项目的 180ms 缓动,不缩放输入文字,也不对 Resizable 连续调宽添加动画。系统开启减少动态效果时直接切换位置。表单实例和草稿在布局变化时保留。
@@ -158,13 +158,45 @@ Agent 形象基于 [Obsidian 原版动画资源](https://ejiidnob33g9ap1r.public
推荐依据使用独立的近期会话页,历史搜索和翻页不改变输入。缓存摘要按活动 ID、标题、内容、状态及来源计算,单纯心跳时间变化不触发推理。生成新推荐时保留上一组问题。
每个会话持有独立 Chat 实例、生成连接、草稿、引用、阅读位置和审批状态。切换历史或新建对话保留原会话后台生成;后台需要审批或回答时,通过历史入口提示返回处理。模型、项目头和凭据续期绑定原会话。后台浏览器动作返回 `SESSION_NOT_ACTIVE`,提示用户回到会话后重新请求;切换时取消原会话尚在执行的浏览器动作。恢复失败保持可重试的连接异常状态,不将断流视为任务完成。切换业务项目由工作台统一处理,会话、主题及缓存按业务项目隔离。
推荐失败后,面板保持打开时在错误缓存到期后重试,同一轮最多请求三次;服务从离线恢复时立即重试失败项,也提供“重试推荐”入口。成功缓存继续复用,重试不改变输入草稿,模型目录尚未加载时不发送空模型请求。
Agent 面板、历史和主题窗口及正文阅读窗口共用选区复制处理,仅移除浏览器附加的末尾段落换行。正文内部段落、代码缩进、表格制表符与用户输入的有效换行保留;输入框沿用原生复制。
每个会话持有独立 Chat 实例、生成连接、草稿、引用、阅读位置和审批状态。切换历史或新建对话保留原会话后台生成;后台需要审批或回答时,通过历史入口提示返回处理。模型、项目头和凭据续期绑定原会话。后台浏览器动作返回 `SESSION_NOT_ACTIVE`,提示用户回到会话后重新请求;切换时取消原会话尚在执行的浏览器动作。切换业务项目由工作台统一处理,会话、主题及缓存按业务项目隔离。
头部在线状态由 Agent 公共 `/health` 的就绪结果独立决定,单次业务失败、提问等待、主动停止和新建对话不直接改为离线或在线。在线时每 15 秒探测,失败后按 1、2、4、8、15 秒退避,单次超时 5 秒;浏览器恢复联网、窗口聚焦或页面重新可见时立即重检。服务恢复后刷新初始化信息和当前会话的提问、输入队列,保留草稿与阅读位置。
已知会话的 Responses 流意外断开后,改用该会话的只读订阅恢复;订阅中断同样按 1 至 15 秒退避重连,合并权威消息尾部并保留已加载历史。重连不重发问题、不重启模型、不重做工具操作,也不将断流视为任务完成。权限失效、会话不存在、主动停止和所属工作台销毁时终止重连;切换到其他对话仍由原会话持有后台恢复连接。
## 4. 内容与状态
### 任务驱动的回答表达
按 Intelligent UI 的声明式组件路线增强当前对话:Agent 使用既有 Harness 与 `present_answer` 决定文字、指标、趋势、对照表、证据及补充表单的组合,前端负责本地交互和视觉层次。简单回答保留文字;说明和判断边界使用本地 shadcn/ui `Alert` 的图标、标题与正文组合,静态历史内容使用 `note` 语义,避免恢复会话时反复播报警告。
包含两类及以上可导航组件,且含表格、图表、补充表单或达到长内容标准时,回答上方出现“浏览回答”菜单,按实际组件显示类别和数量。选中项目在当前内容实例内滚动并交接键盘焦点;Escape 关闭菜单后回到触发按钮。导览沿用 `DropdownMenu`、`Button`、`Badge`,不切换页面、不重建图表或表单。只有一种可导航组件或内容较短时不增加导览。导航入口与内容类别摘要在窄屏保持紧凑,长标签自然换行。
图表保留折线、柱状和数据页签;范围筛选收进标题右侧的控件,所选非完整区间仍明确显示。数据点详情按需展开,点击图上数据点自动展开对应读数;键盘用户通过“查看数据点”及选择器完成同等操作。收起详情保留所选点。当前界面交互均只影响已加载数据;新查询与仿真仍走原业务工具。
消息标题区明确助手身份和真实生成状态。指标保留原始精度、单位与来源;证据继续区分事实和推断;资料表单通过 `CardHeader`、`CardContent` 划分说明和输入,提交是明确的主操作,失败保留填写内容。颜色、字体与表面沿用样式设计指南,交互状态不冒充业务状态。
本次无需新增 UI 协议、环境变量或数据库迁移。自由代码沙箱、跨会话保存控件状态和参数驱动的新数据查询属于后续能力;当前表单、筛选与选择在聊天和展开工作区之间移动时保留,历史恢复仍从已保存的回答结构重新建立控件。
后续的状态保存、压力历史探索与沙箱接入条件见 [可持续分析工作区设计](agent-answer-ui.md#下一阶段设计可持续分析工作区)。该部分是未实现的提案,不能作为当前功能清单。
`answer-ui@1` 仍由严格参数校验与本地注册组件驱动。已有的 `Stack`、`Section`、`Text`、`Metric`、`Table`、`Chart`、`Evidence`、`MapLocation`、`FollowUpForm` 使用新外观。聊天继续使用现有 Responses 事件;正式报告增加可选 `ui_blocks` 字段,复用相同的内容块协议。实现契约见 [本地交互式回答](agent-answer-ui.md)。
生成中显示已经到达的文字、内容块和公开执行摘要;最终答复到达后,正文和它明确引用的内容留在主阅读流,其他记录进入处理过程。待回答问题、权限审批和失败状态保持可见,不能因最终文字到达而被隐藏。这里借鉴 Reasoning 的折叠行为,呈现的数据是服务端已发布的过程信息,不额外生成思考文本,也不根据耗时推算完成比例。
处理过程统一位于回复正文下方。生成中,文字与回答内容块在前,公开执行摘要、标记为过程的内容块和待办在后;最终答复到达或回复流结束后,过程收起为底部“查看处理过程”,入口位于语音播放左侧,没有 `final_answer` 标记的历史回复也遵循同一布局。最终答复明确引用的回答内容块留在主阅读流,其他记录进入处理过程。待回答问题、权限审批和失败状态在正文下方保持可见,不能因回复结束而被隐藏。这里借鉴 Reasoning 的折叠行为,呈现的数据是服务端已发布的过程信息,不额外生成思考文本,也不根据耗时推算完成比例。
最终答复到达后,正文、回复状态与语音/复制操作在同一次交接中切换,网络流的后续收尾不再改变这条回复的展示阶段。输入框仍根据真实执行状态接受引导或排队消息。过程复用生成时的容器和步骤实例,保留工具详情的展开状态;无论用户是否向上滚动或查看过工具详情,交接后默认收起过程并优先让结果正文可读;用户可通过“查看处理过程”重新展开。历史回放直接显示保存的结果,不重新播放交接。
补充问题打断后继续执行时,依据提问记录的 `message_id` 和补充回答的 `delivery.native_message_id` 将前后过程归到续接答复下方;连续补充时沿同一关联链顺序归组。没有正文的旧过程消息不再单独占位,原有正文和用户补充回答仍保留。尚未出现续接答复、历史分页缺少关联消息、仍有待回答问题或审批、关联之间出现新用户请求时,保留原位置。该归组仅影响展示,不改原始记录或消息标识。
生成中、补充后续接和历史恢复共用一个处理过程容器,边框、背景和内边距保持一致;各段执行记录合并为一份列表,不再嵌套另一张“执行进度”卡片。步骤显示身份包含来源消息,避免前后轮次的同名步骤互相覆盖;生成时统一控制整个过程的最近三项与展开全部,完成后由底部入口统一折叠。
已提交的回答以原生用户消息 ID 保存纯净文本和 `data-interaction_reply` 快照,首屏即可还原同一张“已回答”卡片并归组前后过程,不等待独立提问接口。该接口返回较新修订后更新投递状态和重试操作。旧历史由 Agent 按所属会话中已保存的投递 ID 补齐相同表示,不通过文本前缀猜测对应关系,也不改写历史文件。给模型的“用户提交的提问回复”协议前缀只用于推理输入。
提问等待和续接失败不禁用消息发送。生成中或存在未解决的提问/续接时,输入区提供“引导当前任务”和“排队处理”;消息通过既有 Responses 输入接口进入原生收件箱。没有宿主执行轮次时只保存输入,不自行启动模型,也不把消息当作提问表单的答案。读取续接状态时,服务端可以依据已消费的原生回答和已完成的原生输出恢复丢失的确认;仅有部分文字或原生状态不可用时保留未确认状态。若输入在入队前被明确告知当前轮次已结束,客户端刷新状态后作为新一轮发送;其他错误不自动重发。
证据类别明确区分查询记录、用户提供、分析推断和演练数据。地图定位的按钮结果以实际回调为准;资料表单提交后只表示发送消息,业务证据是否保存取决于后端实际结果。最终回复不等于后台调查任务完成。
@@ -184,15 +216,17 @@ Agent 形象基于 [Obsidian 原版动画资源](https://ejiidnob33g9ap1r.public
## 7. 交互规则与范围
数据组件按展示与本地浏览组织:短内容不附加目录;单个证据或补充表单不叠加分组标题与固定提示;来源已在证据卡中显示时,报告外层只列出其余依据。调查脉络节点保留详情、缩放和地图定位,不提供节点追问按钮。
| 内容 | 本轮实现 | 数据与操作边界 |
| --- | --- | --- |
| 指标 | 值、单位、来源,针对指标提问 | 不补造变化率、单位或精度 |
| 表格 | 搜索、三态排序、行选择、引用所选行 | 只处理当前数据;更换数据集时重置行选择 |
| 指标 | 值、单位、来源 | 不补造变化率、单位或精度 |
| 表格 | 搜索、三态排序 | 只处理当前数据;不提供勾选与引用操作 |
| 图表 | 折线 / 柱状 / 数据,序列显隐,加载区间,点击或键盘选点 | 最少保留一条序列;区间不触发查询或重算 |
| 证据 | 来源、类别、时间、编号,展开与类别筛选 | 正式报告使用已保存证据覆盖生成的摘要、来源和类别 |
| 地图 | 显式定位,地图对照或切换 | 使用真实定位结果与失败反馈 |
| 表单 | 空白初始值、必填校验、提交中禁用、失败保留 | 聊天表单主动发送;报告表单先带入对话,确认后发送 |
| 追问 | 输入区引用卡片、详情、移除 | 不自动发送;报告引用带选中的版本与轮次 |
| 任务与报告对话 | 输入区引用卡片、详情、移除 | 保留专用任务、报告和补充表单入口;通用数据组件不产生引用 |
| 历史内容 | 固定报告事实可读,不支持的块显示摘要 | 降级不执行未知组件或事件 |
本轮未包含参数重算、新数据查询控件、附件上传、导出、报告版本差异比较。后续扩展时需要独立定义参数校验、数据来源和执行反馈;不能把本地筛选当作重新分析。后台任务完成、业务审批和证据写入继续以各自服务端状态为准。
@@ -205,14 +239,11 @@ Agent 形象基于 [Obsidian 原版动画资源](https://ejiidnob33g9ap1r.public
组件参数唯一来源为前端 `catalog.ts`,导出到 Agent 与 Server;跨字段约束在三端分别验证。Agent `publish_task_report` 使用正式报告通道,聊天 `present_answer` 使用聊天通道。实现与生成命令见 [本地交互式回答](agent-answer-ui.md)。
## 聊天过程与回答恢复
任务业务审核统一从 header 的“状态和提醒”进入对应任务详情,由关联的负责节点或动作卡承接人工审核。会话只保留任务引用、讨论和消息,不注入固定的任务状态、人工事实或业务审核表单;调查详情继续负责草稿编辑、批准、拒绝及执行回执。工具执行权限审批和用户问题仍按会话交互协议处理。
处理过程统一位于回复正文下方。生成中,文字与回答内容块在前,公开执行摘要、标记为过程的内容块和待办在后;最终答复到达或回复流结束后,过程收起为底部“查看处理过程”,入口位于语音播放左侧,没有 `final_answer` 标记的历史回复也遵循同一布局。最终答复明确引用的回答内容块留在主阅读流,其他记录进入处理过程。待回答问题、权限审批和失败状态在正文下方保持可见,不能因回复结束而被隐藏。这里借鉴 Reasoning 的折叠行为,呈现的数据是服务端已发布的过程信息,不额外生成思考文本,也不根据耗时推算完成比例。
最终答复到达后,正文、回复状态与语音/复制操作在同一次交接中切换,网络流的后续收尾不再改变这条回复的展示阶段。输入框仍根据真实执行状态接受引导或排队消息。过程复用生成时的容器和步骤实例,保留工具详情的展开状态;无论用户是否向上滚动或查看过工具详情,交接后默认收起过程并优先让结果正文可读;用户可通过“查看处理过程”重新展开。历史回放直接显示保存的结果,不重新播放交接。
## 调查报告与自由对话的分工
补充问题打断后继续执行时,依据提问记录的 `message_id` 和补充回答的 `delivery.native_message_id` 将前后过程归到续接答复下方;连续补充时沿同一关联链顺序归组。没有正文的旧过程消息不再单独占位,原有正文和用户补充回答仍保留。尚未出现续接答复、历史分页缺少关联消息、仍有待回答问题或审批、关联之间出现新用户请求时,保留原位置。该归组仅影响展示,不改原始记录或消息标识。
后台调查的固定问答放在右侧调查报告的“补充回答”中,支持选项、自定义文字、提交状态和历史回答。任务通知打开该报告;提交直接保存到原任务并接续调查,无需创建或发送左侧聊天消息。数据缺口旁的“回答当前调查问题”定位到报告内待答表单。
生成中、补充后续接和历史恢复共用一个处理过程容器,边框、背景和内边距保持一致;各段执行记录合并为一份列表,不再嵌套另一张“执行进度”卡片。步骤显示身份包含来源消息,避免前后轮次的同名步骤互相覆盖;生成时统一控制整个过程的最近三项与展开全部,完成后由底部入口统一折叠。
已提交的回答以原生用户消息 ID 保存纯净文本和 `data-interaction_reply` 快照,首屏即可还原同一张“已回答”卡片并归组前后过程,不等待独立提问接口。该接口返回较新修订后更新投递状态和重试操作。旧历史由 Agent 按所属会话中已保存的投递 ID 补齐相同表示,不通过文本前缀猜测对应关系,也不改写历史文件。给模型的“用户提交的提问回复”协议前缀只用于推理输入。
左侧 Agent 保留自由讨论、追问和进一步分析。“Agent 协作”和“讨论此缺口”是明确的讨论入口;固定任务回答不经过这些入口转发。