feat: improve frontend routing and pipeline gantt defaults

This commit is contained in:
Codex
2026-05-07 07:16:44 +00:00
parent 0aa5c1e021
commit 5945c720a6
8 changed files with 2958 additions and 512 deletions
+66 -3
View File
@@ -12,6 +12,18 @@ frontend 应用源码必须使用 TypeScript + React,禁止在 `src/components
左侧边栏只切换主模块:运行总览、资源节点、任务调度、微服务、系统配置。顶部标签只切换当前主模块内的子功能;例如资源节点下的节点清单、资源标签、心跳状态只属于资源节点,微服务下的服务目录、Todo Note、FindJob、Pipeline、MET Nonlinear 只属于微服务,和运行总览、任务调度、系统配置没有重复或共享语义。桌面端左侧边栏必须支持收起,只保留模块 code 和展开按钮,以便最大化主面板空间;移动端左侧边栏会转为顶部横向主模块条,但高度必须在不同主模块之间保持一致,并保持窄条、单行、不换行;主内容区无论内容多少都必须从顶部向下排列,空状态也不得上下居中制造大块留白。
## Route Model
frontend shell 必须把左侧主模块与顶部子标签编译为统一的 URL 路由,而不是在 router 中手工为每个页面逐个挂路径。长期规则如下:
- 导航权威数据只有一份:主模块、子标签、显示文案、route segment、默认子标签都从同一个 TypeScript 导航定义派生,左侧边栏、顶部标签、浏览器地址栏解析和前进/后退都复用同一套 registry。
- Canonical route 必须按主模块前缀分组:运行总览使用 `/ops/<tab-segment>/`,资源节点使用 `/nodes/<tab-segment>/`,任务调度使用 `/tasks/<tab-segment>/`,系统配置使用 `/config/<tab-segment>/`;只有微服务主模块使用 `/app/<tab-segment>/`。例如 `态势总览` 固定为 `/ops/status/``Docker 状态` 固定为 `/nodes/docker/``Pipeline` 固定为 `/app/pipeline/`
- 当 future 需要新增主模块时,通用机制必须允许为该模块声明自己的顶层前缀,而不是继续把所有页面都塞进 `/app/*`
- 主模块根路径如 `/ops/``/nodes/``/tasks/``/app/``/config/` 只作为默认子标签或最近活动子标签的入口别名,实际当前页面仍应落到某个具体子标签;浏览器地址栏不能停留在“只有主模块,没有具体页面”的模糊状态。
- route segment 生成顺序固定为:显式 `routeSegment` > ASCII-safe `id` > 由 label 派生的 Unicode-safe slug > 稳定 hash fallback。这样新增 Unicode 标签时默认仍可得到稳定路径,而不要求每个标签单独写一段路由代码。
- 浏览器直开、刷新、`history.back()` / `history.forward()`、点击总览 drilldown 卡片、点击左侧边栏、点击顶部标签都必须走同一个路由状态机;不得出现“页面内容切换了,但 URL 没变”或“URL 变了,但 shell 仍停在旧 tab”的分裂状态。
- frontend Bun server 必须把这些模块前缀下的深链接路由作为 SPA 入口返回同一个 `index.html`;实现上允许统一把非静态资源路径都回到同一个 shell,但判定标准是公网直开 `/ops/status/``/nodes/docker/``/app/pipeline/` 等深链接时都不得 404。
## Overview Task Drilldown
`态势总览` 中的 `待处理任务` 指标必须可点击进入任务调度的 `待处理任务` 子标签,展示具体 queued、dispatched、running 任务的状态、Provider、已等待时间、payload 摘要和显式 `查看原始JSON` 操作。总览不得只给出无法追溯的数字;当后台把超时未终态任务转为 failed 后,待处理指标应回落,历史记录仍可在任务历史和执行结果中查看。核心指标还必须展示 `PGDATA`,显示 PostgreSQL 当前数据库用量、命名卷 `unidesk_pgdata_10gb` 和配置容量,便于从总览判断数据库状态。
@@ -42,9 +54,60 @@ frontend 应用源码必须使用 TypeScript + React,禁止在 `src/components
## Microservice Frontend
`微服务` 主模块用于展示挂载在计算节点或主 server Docker 中的业务后端。`服务目录` 必须显示 service id、Provider、仓库 URL、commit id、业务 Dockerfile/docker-compose 引用、节点后端私有映射、SSH 透传开发入口和运行态容器摘要;`Todo Note` 子标签必须把主 server `todo-note-backend` 后端渲染为 UniDesk React 控件,包括迁移清单、树形任务、筛选、提醒、拖放/移动、撤销/重做、字号控制和显式原始 JSON 按钮;`FindJob` 子标签必须把 D601 findjob 后端渲染为 UniDesk React 控件,包括岗位指标、岗位预览、草稿报告和显式原始 JSON 按钮;`Pipeline` 子标签必须把 D601 `/home/ubuntu/pipeline` 后端渲染为组件矩阵、React Flow 控制图框图、epoch 列表、运行材料索引、epoch 甘特图和 node 精细控制面板,用户点击控制图中的 node 后必须能通过同源 microservice 代理抓取该 node 执行过程、向运行中 node 追加 prompt、给下次尝试下发 guide,以及排队 restart/redo`MET Nonlinear` 子标签必须把 D601 `/home/ubuntu/met_nonlinear` 的训练编排后端渲染为下载器式工作台,包括项目库选择、从已有 Project fork 新 Project、加入待启动队列、启动队列、最大并发设置、当前队列、已完成、失败诊断、GPU/镜像、训练进度、ETA、历史记录和显式原始 JSON 按钮;运行中训练若后端未直接给出 ETA,前端必须用 `startedAt`、当前 epoch 和目标 epoch 做可解释的剩余时间估算;训练队列和已完成列表必须显示训练速度 `epoch/h`。MET Nonlinear 项目库必须按真实文件路径分层显示 `projects/``ex_projects/`,文件夹计数必须等于其子树中的 Project 数,不能用模型名、状态或其他派生字段替代文件树层级。项目库、当前队列、已完成和失败诊断中的行必须可点击打开结构化详情;详情必须把 `config.json``data/training_state.json``data/training_info.json``data/metrics.json``data/model_info.json``data/compute_analysis.json` 中的训练状态、模型参数量、模型层、指标和 data 文件清单渲染为字段卡、表格和 chip,不得默认显示裸 JSON。不得提供硬编码的固定数量/固定轮数测试按钮。该模块不得 iframe 业务旧前端、Todo Note 原 Vite 前端或 Pipeline 自身 WebUI,不得把 microservice 后端端口暴露为浏览器直连 URL,也不得把业务 API 的 JSON 裸铺在页面上。
Pipeline 的一个 epoch 定义为同一个 pipeline 从入口到终态完整执行一遍。Pipeline 前端必须把同一 `pipelineId` 下的多个 run 作为多个 epoch 展示,并允许操作员切换当前 epoch;控制图、node 控制面板、运行材料索引和甘特图都必须跟随当前 epoch。epoch 甘特图的纵轴是时间,左侧第一列展示时间刻度,后续每列对应一个 node;node 在 `startedAt``finishedAt` 或当前时间之间处于工作态时绘制竖向工作条,空闲时间留空。甘特图必须根据当前可见时间窗口自动隐藏该窗口内没有任何工作区间的 node 列,避免宽图把无关空闲 node 挤在屏幕中。Pipeline 默认界面不得以一行一条 JSON、JSONL、worker log 或 control event 的形式展示“证据”;运行材料只能作为结构化索引行展示计数、状态、时间和来源摘要,完整 JSON、JSONL 或 log tail 只能通过显式 `查看原始JSON` 按钮打开
- `微服务` 主模块用于展示挂载在计算节点或主 server Docker 中的业务后端。
- `服务目录` 必须显示 service id、Provider、仓库 URL、commit id、业务 Dockerfile/docker-compose 引用、节点后端私有映射、SSH 透传开发入口和运行态容器摘要。
- `Todo Note` 子标签必须把主 server `todo-note-backend` 后端渲染为 UniDesk React 控件,包括迁移清单、树形任务、筛选、提醒、拖放/移动、撤销/重做、字号控制和显式原始 JSON 按钮。
- `FindJob` 子标签必须把 D601 findjob 后端渲染为 UniDesk React 控件,包括岗位指标、岗位预览、草稿报告和显式原始 JSON 按钮。
- 业务 microservice 页面不得 iframe 业务旧前端、Todo Note 原 Vite 前端或 Pipeline 自身 WebUI,不得把 microservice 后端端口暴露为浏览器直连 URL,也不得把业务 API 的 JSON 裸铺在页面上。
- `Pipeline` 子标签是 D601 `/home/ubuntu/pipeline` 的 UniDesk host UI。
- 基础视图必须包含组件矩阵、React Flow 控制图框图、epoch 列表、运行材料索引、epoch 甘特图和 node 精细控制面板。
- 用户点击控制图中的 node 后,必须通过同源 microservice 代理抓取该 node 执行过程,并支持向运行中 node 追加 prompt、给下次尝试下发 guide、对已完成 node 排队 modify、提交 monitor 审核 approve,以及排队 restart/redo。
- append-prompt、guide、modify、redo/restart 统称为 node 的管理行为;approve 是 monitor 审核决策;fetch/status 只属于观察行为。
- UniDesk 只负责同源代理、结构化展示和人工控制入口,不直接写 Pipeline `.state` 文件。
- node 精细控制面板的 append、guide、modify、approve、redo/restart 必须调用 Pipeline HTTP node-control 后端,并把 WebUI 发起者记录为结构化 `sourceKind=webui` 事件。
- `Pipeline` epoch 和甘特图规则。
- 一个 epoch 定义为同一个 pipeline 从入口到终态完整执行一遍。
- 同一 `pipelineId` 下的多个 run 必须作为多个 epoch 展示,并允许操作员切换当前 epoch;控制图、node 控制面板、运行材料索引和甘特图都必须跟随当前 epoch。
- epoch 下拉框必须通过同源 snapshot 轮询自动看到新 run,不能依赖浏览器强制刷新,但也不应在用户已选中旧 epoch 时自动跳走。
- 甘特图默认时间尺度固定为 `100 px/min`,并且默认关闭 `自动隐藏空闲列`,让操作员首次进入页面时先看到完整 node 列。
- epoch 甘特图的纵轴是时间,左侧第一列展示时间刻度,后续每列对应一个 node;node 在 `startedAt``finishedAt` 或当前时间之间处于工作态时绘制竖向工作条,空闲时间留空。
- 甘特图 node 列顺序必须遵循 pipeline 拓扑,从上游到下游依次向右展开;不得把下游 node 排在上游左侧。
- 甘特图必须提供时间尺度滑块,用同一份时间数据调整每分钟像素密度:全局尺度压缩纵向高度以查看完整 epoch,细节尺度拉长纵向高度以查看短时间内的 prompt 点、控制点和执行线。
- 精确数学图形的坐标权威规则。
- 凡是精确时序图、甘特图或其他包含严格数学映射关系的渲染,坐标权威必须在后端完成。
- Pipeline `GET /api/node-control/runs/{runId}?view=gantt&scale=0..100` 应返回可直接展示的 `layout.chartHeight`、时间刻度 `ticks[].y`、执行区间 `startY/endY/y1/y2/height`、事件点 `y/timeAxisY`、控制箭头 `sourceY/targetY/y1/y2` 和对齐诊断。
- UniDesk 前端在该 DTO 存在时不得独立把时间戳重新换算为 y 轴坐标,只能按后端坐标纯展示。
- 时间尺度滑块变化必须重新请求后端布局。
- 甘特图必须根据当前可见的后端 y 区间自动隐藏该窗口内没有任何工作区间或事件点的 node 列,避免宽图把无关空闲 node 挤在屏幕中。
- `Pipeline` 甘特图事件来源。
- 甘特图上的执行线、prompt 点、控制点和 monitor 虚线箭头必须通过同源 `node-control` HTTP 读取接口驱动。
- run 级图形数据使用 `GET /api/node-control/runs/{runId}?view=gantt&scale=0..100`
- node 级 OpenCode 明细来自用户选择后的 `GET /api/node-control/runs/{runId}/nodes/{nodeId}`,避免跨 UniDesk provider HTTP 代理时一次性拉取全 run 的大体积 step 数组。
- prompt 点来源于 attempt 级 `controlEventRecords` 中的 prompt-delivered 事件,必要时回退到 `controlPromptRecords` / `monitorPromptRecords`
- 控制点和 monitor/人工控制箭头来源于 run 级 `controlEvents`,必要时回退到 `controlCommands`
- 控制事件必须依赖后端记录的 `sourceKind``sourceNodeId``targetNodeId``commandId``eventId``resetNodeIds``interruptedProcedureRunIds` 等结构化字段识别 monitor、WebUI、CLI 等发起者,不能通过解析 monitor 自己的 step 文本来反推。
- `Pipeline` monitor 审核与详情展示。
- Pipeline 后端可通过 `control.monitoring.audit.enabled=true` 开启 monitor 审核门禁。
- 当前 pipeline 存在 monitor node 时,node 成功后必须等待后端记录的 `approve` 审核通过,或由 monitor 发起 `modify` 增量修改管理行为、`redo/restart` 重做管理行为。
- 前端应把审核/控制事件渲染为结构化点和虚线箭头。
- 点击甘特图中的执行线、prompt 点或控制点后,右侧边栏必须展示结构化事件字段、匹配的 procedure/attempt、以及对应 OpenCode step 的摘要与展开详情,而不是在主界面直接铺 raw JSON、JSONL、worker log 或 control event 文本。
- OpenCode step 展示必须参考 `~/.agents/skills/agent-sessions/scripts/webui/src/components/MessageList.tsx` 的信息组织方式:按消息流时间线展示角色、模型、tokens、创建/完成时间,正文摘要直接可读,思考和工具调用分区折叠,工具调用要显示工具名、状态、输入字段、输出摘要和元数据。
- 右侧边栏中的 OpenCode Step Timeline 必须把公共 session 信息(agent、model、session id)聚合到 session 头部,不得在每个 step 重复;单个 step 的默认摘要只保留时间、消息、工具调用三类信息,统计信息和 tag 必须折叠到展开层。
- 右侧边栏排版必须优先保护横向可读宽度:时间放在 step 顶部 header,而不是单独占用左侧窄列;默认摘要不得引入右侧边栏内部横向滚动条,也不得因为窄列挤压把 step 高度拉得过高。
- 调整任何高信息密度右侧边栏布局时,都必须把 `总高度``横向滚动条` 作为显式验收指标,用 Playwright 打开真实页面验证,而不是只看静态代码或本地想象。
- 运行材料只能作为结构化索引行展示计数、状态、时间和来源摘要,完整 JSON、JSONL 或 log tail 只能通过显式 `查看原始JSON` 按钮打开。
- `Pipeline` 渲染与算法验证。
- 涉及 monitor 审核、管理行为或甘特图算法的改动,必须用 Pipeline 侧通用 fixture 组合验证。
- 验证组合至少包括拓扑 split/merge/feedback、生产型 PikaPython workflow、`monitor-management-behavior-test``monitor-audit-behavior-test`
- 所有 fixture 都应走同一渲染与事件解析路径;不得为了某个 pipeline id、node id 或 run id 在 UniDesk 前端加入特例。
- `MET Nonlinear` 子标签必须把 D601 `/home/ubuntu/met_nonlinear` 的训练编排后端渲染为下载器式工作台。
- 工作台包括项目库选择、从已有 Project fork 新 Project、加入待启动队列、启动队列、最大并发设置、当前队列、已完成、失败诊断、GPU/镜像、训练进度、ETA、历史记录和显式原始 JSON 按钮。
- 运行中训练若后端未直接给出 ETA,前端必须用 `startedAt`、当前 epoch 和目标 epoch 做可解释的剩余时间估算。
- 训练队列和已完成列表必须显示训练速度 `epoch/h`
- 项目库必须按真实文件路径分层显示 `projects/``ex_projects/`,文件夹计数必须等于其子树中的 Project 数,不能用模型名、状态或其他派生字段替代文件树层级。
- 项目库、当前队列、已完成和失败诊断中的行必须可点击打开结构化详情。
- 详情必须把 `config.json``data/training_state.json``data/training_info.json``data/metrics.json``data/model_info.json``data/compute_analysis.json` 中的训练状态、模型参数量、模型层、指标和 data 文件清单渲染为字段卡、表格和 chip,不得默认显示裸 JSON。
- 不得提供硬编码的固定数量/固定轮数测试按钮。
## Component Data Rendering