状态基线:2026-09-02。本文明确区分“当前运行架构”“独立执行面原型”和“目标部署架构”,避免把规划写成已实现事实。
- 可恢复:任务可暂停、审批、重试,并可由事件历史恢复 UI 状态。
- 可复现:实验最终要绑定数据、代码、环境、参数、随机种子和指标。
- 可追溯:Agent 阶段、审批、产物和论文结论有统一运行身份。
- 界面稳定:后端语义进入现有 14 个 Web 页面,不以对接为由重做界面。
- 本地优先、可演进:本地 PostgreSQL 与内容存储先可用,再平滑替换为服务化底座。
flowchart LR
subgraph Web["apps/web"]
Routes["14 条静态路由"]
Templates["现有 HTML/CSS 页面模板"]
TaskStart["新任务控制器"]
Controller["建模工作台控制器"]
Account["账户与安全客户端"]
end
subgraph API["backend/api"]
FastAPI["FastAPI"]
Workspace["ModelingWorkspaceView 投影"]
Runner["内嵌 RunnerThread"]
Engine["agents/core 状态机 + 真实/模拟节点"]
end
subgraph LocalData["当前数据面"]
PG[("PostgreSQL")]
Blob["本地内容寻址 Artifact Store"]
end
Routes --> Templates
Templates --> TaskStart
Templates --> Controller
TaskStart -->|"登录 / 创建 Project 与 TaskRun"| FastAPI
Controller -->|"GET workspace / POST actions"| FastAPI
FastAPI -->|"SSE"| Controller
Account -->|"/api/auth /api/account"| FastAPI
FastAPI --> Workspace
Workspace --> PG
FastAPI --> Runner
Runner --> Engine
Engine --> PG
Engine --> Blob
当前事实:
- Web 继续由
App.tsx的路径映射、OpenMathModelScreen和openmathmodel-ui.ts生成页面。 - 首页通过
task-start-controller.ts保存草稿,发送时恢复登录并直接创建真实 Project/TaskRun,把run_id/project_id交给执行页;/confirm是直接访问时的草稿复核入口,共用同一套提交流程。附件支持二进制上传与服务端文本抽取(扫描件经远程 OCR)。账户与安全页面使用正式 API。 - 六个建模流程页面都会挂载
modeling-workspace-controller.ts,仅在 URL 或同标签页 sessionStorage 提供合法运行身份时请求 workspace API。 GET /api/v1/task-runs/{run_id}/workspace聚合运行、步骤、待审批项和产物,作为 Agent 左栏与阶段页面状态的共同语义来源;它当前不提供右侧详细正文。- Web 首屏取快照,随后订阅 SSE;阶段或产物事件触发快照刷新。
- API 使用 PostgreSQL(限定数据库,默认连
tools/pg-dev.ps1的本地 5433 实例,schema 以 Alembic 为准)、本地 Artifact Store 和进程内RunnerThread;SQLite 仅测试夹具作临时隔离库使用。 - 配置了自定义 API 的用户,六个建模阶段全部由
agents/skills真实节点执行(实验阶段经agents/tools的 python 沙箱运行生成代码);未配置或提示词缺失时整链回落SimStageNode模拟节点。
完整的前后端与 Agent 映射见前后端与 Agent 工作台对接规范。
当前浏览器主链已经从首页输入延伸到真实 TaskRun:
首页输入与附件元数据
→ sessionStorage TaskDraft
→ 发送:fetchMe / 现有登录模态续接
→ POST /api/v1/projects
→ POST /api/v1/task-runs(稳定 Idempotency-Key)
→ /task/running?run_id=...&project_id=...
/confirm 不在首页发送链路上:直接访问时恢复草稿复核,“开始任务”执行同一套提交流程;无草稿时进入显式 demo=1,不创建后端资源,也不复用旧 activeRunId。API 或身份错误停留在当前页(首页或确认页)并原位显示状态;重新发送未修改的草稿沿用已写回的 project_id 与幂等 token,不重复创建。
工作台恢复切片随后以后端返回的 run_id 为起点,覆盖工作台快照、Agent 时间线与摘要、模型方案审批、SSE 刷新,以及实验/完成页的真实 Artifact 文件清单。五类页面正文投影(GET /task-runs/{run_id}/stage-outputs)、附件上传/解析、G2 数据闸门确认、论文导出与完成后修订回合(ADR-0013)也已接入;仍不包含论文编辑保存(乐观锁)、可见的暂停入口和独立 Worker 的生产接线。
URL run_id
→ GET /api/v1/task-runs/{run_id}/workspace
→ ModelingWorkspaceView
→ 现有页面 DOM 适配器
├─ 顶部项目名与运行状态
├─ 左侧 Agent 时间线、摘要和主操作
├─ 右侧阶段状态
└─ 实验/完成页 Artifact 文件行
→ EventSource /events?after=<latest_sequence>
→ 事件到达后重新获取快照
运行身份的实际解析顺序是:URL 显式 demo=1 时优先进入演示状态;否则,URL 中存在且格式合法的 run_id 优先并写入 sessionStorage,URL 未提供 run_id 时才读取同一标签页中合法的 sessionStorage.openmathmodel.activeRunId。URL 显式提供非法值,或两处都没有合法值时进入 demo 状态并且不请求 workspace API。
suggested_route 是导航建议,不是命令。用户打开的流程页与 active_page 不一致时,控制器仍在当前页面渲染同一快照,并把主操作降为“前往当前阶段”;只有用户点击后才跳转。错页加载本身不提交 /actions,也不推进、审批或改变 TaskRun 状态。
审批链路已经闭环:
MODEL_PLANNING
→ ApprovalRequest(PENDING)
→ workspace.agent.action(kind=approve)
→ Web POST /actions(Idempotency-Key)
→ approval.resolved / run.node_changed SSE
→ workspace 快照刷新
→ Agent 时间线与主操作同步更新
事件是增量通知,快照是页面恢复依据。Web 不从 run.log 自然语言拼装表格或论文。
backend/worker 已具备文件队列、租约、JSONL 事件恢复、沙箱和工作区产物能力,但当前 API 未导入或调度 omm_worker。它是下一阶段执行面原型,不是当前 API 请求链的一部分。
配置了自定义 API 的用户,六个建模阶段已全部由 agents/skills 真实节点执行(实验阶段经 agents/tools 的 python 沙箱运行生成代码);未配置或提示词缺失时整链回落 SimStageNode。文档和 UI 仍须把模拟阶段产物标识为模拟,不把它描述为完整生产智能体。
| 数据 | 当前事实来源 | Web 消费方式 |
|---|---|---|
| 运行生命周期 | task_runs |
ModelingWorkspaceView.run_status/active_node |
| 阶段尝试 | step_runs |
pages[].status 聚合结果 |
| 审批 | approval_requests |
pending_approval 与 agent.action |
| 实时通知 | agent_events |
SSE,sequence 单调递增 |
| 文件元数据 | artifacts |
artifacts[] 与下载 URL |
| 二进制内容 | 本地 Blob Store | /api/v1/artifacts/{id}/download 下载时校验 SHA-256 |
| 用户头像 | users.avatar_sha256 + 独立头像内容存储 |
user.avatar_url 带摘要查询串,/api/account/avatar 仅返回本人头像 |
| 页面详细正文 | stage_outputs(STEP_SUCCEEDED 最新成功产出的投影) |
GET /api/v1/task-runs/{run_id}/stage-outputs 五类正文投影 |
领域事件表是执行事实来源,控制面表和 ModelingWorkspaceView 是查询投影。UI 不直接读取数据库或 Worker 文件。
后端输出语义,前端拥有表现:
- 后端:阶段、状态、纯文本摘要、允许动作、审批 ID、产物引用。
- 前端:HTML、CSS、图标、页面标签、表格布局、编辑器和响应式行为。
- Agent 输出不携带 HTML、CSS 类名或 DOM 选择器。
- 同一
ModelingWorkspaceView同时驱动 Agent 左栏和右侧页面,避免两个区域展示不同阶段。
节点到页面的当前映射:
| 节点 | 页面 |
|---|---|
CREATED / PROBLEM_ANALYSIS |
/task/running |
DATA_PREPARATION |
/workspace/data |
MODEL_PLANNING |
/workspace/model-plan |
EXPERIMENTING / VALIDATING |
/workspace/experiments |
PAPER_WRITING |
/workspace/paper-editor |
COMPLETED |
/task/complete |
GET /api/health
POST /api/auth/*
GET/PATCH/POST/DELETE /api/account/*(含 llm-config、privacy-settings、2FA、sessions)
GET/POST/DELETE /api/account/avatar
POST /api/chat;POST /api/llm/test、/api/llm/models
GET/PUT /api/usage/*(summary、export、settings)
POST /api/v1/task-intake
POST/GET /api/v1/projects
GET/PATCH/DELETE /api/v1/projects/{project_id}
POST/GET /api/v1/projects/{project_id}/artifacts
POST/GET /api/v1/task-runs
GET /api/v1/task-runs/{run_id}
GET /api/v1/task-runs/{run_id}/steps
GET /api/v1/task-runs/{run_id}/approvals
POST /api/v1/task-runs/{run_id}/actions
POST /api/v1/task-runs/{run_id}/notes
POST /api/v1/task-runs/{run_id}/revisions
GET /api/v1/task-runs/{run_id}/workspace
GET /api/v1/task-runs/{run_id}/stage-outputs
GET /api/v1/task-runs/{run_id}/events/history
GET /api/v1/task-runs/{run_id}/events
POST /api/v1/artifacts/parse
GET /api/v1/artifacts/{artifact_id}/download
GET /api/v1/artifacts/{artifact_id}/text
POST /api/v1/paper-exports
GET /api/v1/paper-exports/{export_id}
错误信封统一为 code、message、request_id、details。当前 TaskRun 创建与 TaskRun /actions 使用 Idempotency-Key;这不是对所有写接口的统一实现声明。受保护资源按项目 owner 隔离。
packages/contracts/schemas/v1/modeling-workspace-view.schema.json 是工作台快照事实来源,生成 Python 与 TypeScript 类型。它包含:
- 运行与项目身份;
- 当前节点、当前页面、建议路由;
- Agent 状态、摘要、当前步骤和允许动作;
- 六个流程页面的状态与产物 ID;
- 带状态的产物元数据;只有
READY且具有完整存储引用与哈希的 Artifact 才提供download_url; - 当前待审批项与最新事件序号。
工作台快照解决“当前在哪、Agent 显示什么、可以做什么、有哪些文件”,各阶段正文数据由五类契约经 GET /api/v1/task-runs/{run_id}/stage-outputs 提供(STEP_SUCCEEDED 最新成功产出的只读投影,交付清单只列最近一趟产物):
| 页面 | 契约 | 关键内容 |
|---|---|---|
| 数据准备 | DatasetProfile |
指标、问题、预览、清洗记录、字段字典 |
| 建模方案 | PlanProposal |
2–3 个角色化方案、假设、符号、实现计划 |
| 实验结果 | ExperimentSummary |
指标、图表、稳健性、运行环境、产物分组 |
| 论文编辑 | DocumentDraft |
版本、大纲、章节、引用与检查 |
| 最终成果 | DeliveryManifest |
摘要、限制、交付文件、哈希与一致性检查 |
论文编辑的保存与版本冲突处理(乐观锁写路径)尚未落地;正文缺失时对应区域回落页面模板,不得从日志文本反向解析填充。
Artifact 投影是一份真实文件清单,而不是由前端生成的交付压缩包。PENDING、STALE、DELETED 仍可作为状态行显示,但下载按钮禁用;“导出文件清单”只导出名称、类型、状态、大小与下载地址的文本清单,不创建 ZIP 或合并归档。
目标态才使用下列链路:
flowchart LR
Clients["Web / Desktop"] --> API["API 副本"]
API --> PG[("PostgreSQL")]
API --> Queue["Redis / Job Queue"]
Queue --> Workers["Worker 池"]
Workers --> Agent["真实 Agent 节点注册表"]
Workers --> Object[("S3 / MinIO")]
Workers --> PG
PG --> Events["事件通知"]
Events --> Clients
迁移原则:先保持现有 API 与契约不变,再替换执行与存储端口;不以部署升级为由更换页面路由或视觉结构。
- API 与独立 Worker 尚未贯通;执行面是进程内
RunnerThread单线程逐节点轮转,「最大并发任务」设置尚不产生真并行。 - 真实节点依赖用户配置自定义 API;未配置时仍为
SimStageNode模拟链路。 - 论文编辑的保存与版本冲突处理(
DocumentDraft乐观锁写路径)尚未落地。 - 六阶段节点读取附件时仅使用浏览器摘录(每附件前 1200 字、合计 4000 字);服务端全文抽取(含远程 OCR 结果)当前只服务对话路径,尚未注入六阶段节点。
- Artifact 血缘目前仍未完整投影。
- 当前 API 自动化已经覆盖排队、待审批、完成态、完成页产物聚合、非 READY Artifact、跨项目异常关联、跨账户 404、删除/清扫链路(PostgreSQL 双方言)与 OpenAPI 组件兼容。web 包无 DOM 测试栈,浏览器自动化仍待补齐;ADR-0013 修订回合已于 2026-09-02 经无头浏览器实机走查验收。
这些项是后续开发清单,不影响当前工作台状态、审批和产物元数据闭环的可用性。