feat(controller): mermaid workflow rendering + task-level inspection API - #1230
Conversation
- Add shared workflow.Snapshot + RenderMermaid (internal/workflow): the
agt CLI --mermaid and the new API format both render from one renderer.
Node labels carry status; next/ready nodes get the ready highlight,
other nodes a status class (pending/delegated/inProgress/completed/
revision/blocked); all classDefs emitted for standalone rendering.
- GET /api/v1/projects/{id}/workflow?format=mermaid returns the same
snapshot as text/plain mermaid (unknown format -> 400).
- GET /api/v1/projects/{id}/tasks/{taskId} (node-level inspection):
graph node + TaskMeta (spec/summary/result/deliverables) + append-only
transition history (task meta history[], cap 50; empty until the
transition engine lands, design agentscope-ai#1223) + trace hint (worker entry
spans carry agentteams.project.id/task.id). Same access model as the
artifact endpoint: isSafeTaskID, graph membership, W4 404
existence-hiding, owning-scope-only TaskMeta (no cross-scope fallback).
- taskDetail gains an omitempty history field, so ?includeTasks=true
exposes the same audit once transitions are recorded.
- Docs: project-workflow-api.md (en + zh-cn) cover both endpoints and
the --mermaid renderer change.
|
Thanks for extending the workflow inspection surface. The project-scoped authorization and the no-global-fallback lookup in the task detail path look aligned with the existing API boundaries. Before this moves out of draft, please address the following:
Once these are addressed and CI is green, please mark the PR ready for review. |
Reviewer follow-up on agentscope-ai#1230: - RenderMermaid now sanitizes user-controlled titles and task ids so a malformed title can never alter the rendered graph structure: newlines -> <br>, double quotes -> #quot;, backslashes dropped, control chars -> space; task ids with characters outside [A-Za-z0-9_-] map to a collision-safe node id (labels keep the original text). New safety tests cover the reviewer-requested cases (quotes, newlines, brackets, edge-like syntax, control characters, unicode - 7 malformed-title cases) plus a structure-invariant test (a hostile title must not create extra nodes or edges) and an id-collision test (t.1 and t_1 stay distinct). - Docs (en + zh-cn) + taskTraceHint comment: the trace object is a tracing-backend filter hint whose project_id/task_id are the values for the agentteams.project.id / agentteams.task.id span attributes (previously worded as 'attribute names' while returning values).
|
@shiyiyue1102 1. Mermaid-sensitive titles — fixed.
Added safety tests for exactly the requested cases — quotes, newlines, brackets, edge-like syntax ( 2. 3. CI — green on
For the record on the hermes-shard failure: it was The PR is marked ready for review. Happy to address anything else. 感谢 review——三点已在 1. Mermaid 敏感标题——已修复。
新增了覆盖所要求全部用例的安全测试——引号、换行、括号、edge 语法( 2. 3. CI——
hermes shard 失败记录在案:失败的是 PR 已转为 ready for review,如有其他意见随时提出。 |
shiyiyue1102
left a comment
There was a problem hiding this comment.
LGTM. The updated Mermaid renderer safely handles user-controlled labels and task IDs, the task inspection endpoint preserves the existing project/team access boundary, and the trace contract is now documented consistently. The current head 707b019d has no failing or pending checks.
matrix.Client gained SendNotification in main (agentscope-ai#1230 task inspection API); the team provisioner test fake no longer satisfied the interface. Sync the fake so the package builds against current main.
matrix.Client gained SendNotification in main (agentscope-ai#1230 task inspection API); the team provisioner test fake no longer satisfied the interface. Sync the fake so the package builds against current main.
matrix.Client gained SendNotification in main (agentscope-ai#1230 task inspection API); the team provisioner test fake no longer satisfied the interface. Sync the fake so the package builds against current main.
matrix.Client gained SendNotification in main (agentscope-ai#1230 task inspection API); the team provisioner test fake no longer satisfied the interface. Sync the fake so the package builds against current main.
Summary
Part 1 (read-only observability) of the workflow engine design in
#1223: no new
writes, no schema changes — only new read paths and one shared renderer.
GET /api/v1/projects/{id}/workflow?format=mermaid— the existingLangGraph-aligned workflow snapshot rendered as a Mermaid flowchart
(
text/plain), so any Mermaid-capable UI (dashboards, plugins, docs) canembed a live DAG without re-implementing graph layout. Unknown
formatvalues return400; the default JSON response is byte-identicalto before.
GET /api/v1/projects/{id}/tasks/{taskId}— node-level inspection:the task's graph node (status / assignee / dependencies), its TaskMeta
(spec / summary / result / deliverables), the append-only transition
history[](populated once the transition engine lands — see Design: Project workflow engine — transition event stream, node-level state inspection, and graph export #1223), anda
tracehint naming the tracing attributes worker entry spans alreadycarry (
agentteams.project.id/agentteams.task.id).internal/workflow) — theagt --mermaidCLI and the new API format render from the same code. Node labels keep
name: status; next/ready nodes get thereadyhighlight and everyother node is now colored by status (
pending/delegated/inProgress/completed/revision/blocked). All classDefs areemitted so the graph renders standalone (previously only
ready).What's included
internal/workflow(new package, zero dependencies):Snapshot/Node/Edgetypes +RenderMermaid— usable by both the controllerAPI and the
agtCLI without the CLI importing the (K8s-heavy) serverpackage
GET /api/v1/projects/{id}/workflow?format=mermaid— same access modelas the JSON workflow endpoint (single K8s List for prefix resolution +
access check; 404 existence-hiding for scoped callers);
includeTasksis ignored for mermaid (rendering needs only nodes/edges/next)
GET /api/v1/projects/{id}/tasks/{taskId}— same access model as theexisting artifact endpoint:
isSafeTaskIDvalidation, graph membershipcheck (a task id from another project → 404), owning-scope-only TaskMeta
read (a team project never falls back to a global TaskMeta — same rule as
tasks_detail), ownership check (task_id+project_idmust match)taskDetailgains an omitemptyhistoryfield, so?includeTasks=truealso exposes transition history once it exists(additive; existing consumers unaffected)
agt get projects <id> --mermaidnow uses the shared renderer (outputgains status classes; structure unchanged)
docs/usage/project-workflow-api.md+docs/zh-cn/usage/...—formatparameter, the new inspection endpoint, and the CLI change(also removes two stale internal code references from the zh-cn
headings)
Behavior
GET .../workflow(no params)GET .../workflow?includeTasks=truetasks_detailhistory(omitempty)GET .../workflow?format=mermaidtext/plainMermaid flowchartGET .../workflow?format=bogus400GET .../tasks/{taskId}agt get projects <id> --mermaidreadyclass onlyTests
internal/workflow: renderer unit tests — status classes, readyoverride, empty graph, all classDefs present (4 tests)
internal/server(8 new, 0 regressions in the full package suite):classDefs;
format=bogus→ 400skipped) + dependencies + trace hint; missing TaskMeta → node summary
only (normalized status); task not in graph → 404; invalid task id →
400; loop-plan task; cross-scope no-fallback (team project must not
leak a global TaskMeta)
cmd/agt: CLI integration test — JSON →Snapshot→ render (the exact--mermaidpath)go build/go vet/go testgreen oninternal/server,internal/workflow,cmd/agt; gofmt cleanCompatibility
worker-runtime changes
package test suite, unmodified)
omitempty; the new route does not shadow theexisting
.../tasks/{taskId}/artifactroute摘要
工作流引擎设计(#1223)的第 1 部分(只读可观测):不新增写入、不改 schema,只加读路径和一个共享渲染器。
GET /api/v1/projects/{id}/workflow?format=mermaid—— 现有 LangGraph 对齐工作流快照渲染为 Mermaid 流程图(text/plain),任何支持 Mermaid 的 UI(dashboard/插件/文档)可直接嵌入实时 DAG,无需自研图布局。未知format返回400;默认 JSON 响应字节级不变。GET /api/v1/projects/{id}/tasks/{taskId}—— 节点级检视:任务的图节点(状态/负责人/依赖)、TaskMeta(spec/摘要/结果/交付物)、append-only 状态迁移history[](状态机落地后由 Design: Project workflow engine — transition event stream, node-level state inspection, and graph export #1223 的设计填充),以及trace提示(worker entry span 已携带agentteams.project.id/agentteams.task.id属性)。internal/workflow)——agt --mermaidCLI 与 API 新 format 走同一份代码。节点标签保持name: status;next/ready 节点高亮ready,其余节点按状态着色(pending/delegated/inProgress/completed/revision/blocked)。所有 classDef 均输出,图可独立渲染(此前仅ready)。包含内容
internal/workflow(新包,零依赖):Snapshot/Node/Edge类型 +RenderMermaid—— controller API 与agtCLI 共用,CLI 无需导入(含 K8s 依赖的)server 包GET .../workflow?format=mermaid—— 与 JSON workflow 端点相同访问模型(单次 K8s List 完成前缀解析 + 鉴权;限定读者 404 隐藏存在性);mermaid 忽略includeTasks(渲染只需 nodes/edges/next)GET .../tasks/{taskId}—— 与现有 artifact 端点相同访问模型:isSafeTaskID校验、图成员检查(其他项目的 task id → 404)、仅从项目所属 scope 读 TaskMeta(team 项目绝不回退 global TaskMeta —— 与tasks_detail同规则)、所有权校验(task_id+project_id必须匹配)taskDetail增加 omitemptyhistory字段 ——?includeTasks=true同样暴露迁移历史(纯增量,既有消费者不受影响)agt get projects <id> --mermaid改走共享渲染器(输出增加状态 class,结构不变)project-workflow-api.md中英双份 ——format参数、新检视端点、CLI 变更(顺带清除 zh-cn 标题中两处过时的内部代号引用)测试
internal/workflow:渲染器单测 —— 状态 class、ready 覆盖、空图、classDef 齐全(4 个)internal/server(8 个新测试,全包 0 回归):mermaid format(content-type / 节点标签 / ready 覆盖 / 边 / classDef;format=bogus→ 400);task 检视(完整 detail + 解析 history(畸形条目跳过)+ 依赖 + trace 提示;TaskMeta 缺失 → 仅节点摘要(归一化状态);任务不在图中 → 404;非法 task id → 400;loop 计划任务;跨 scope 不回退(team 项目不得泄漏 global TaskMeta)cmd/agt:CLI 集成测试 —— JSON →Snapshot→ 渲染(--mermaid实际路径)go build/go vet/go test(internal/server、internal/workflow、cmd/agt)全绿;gofmt 干净兼容性
omitempty;新路由不与既有.../tasks/{taskId}/artifact路由冲突