# 自动流程图助手 **Repository Path**: godbirds/dsh-autoflower ## Basic Information - **Project Name**: 自动流程图助手 - **Description**: 自动生成流程图,可对流程图进行微调 - **Primary Language**: Unknown - **License**: MIT - **Default Branch**: master - **Homepage**: None - **GVP Project**: No ## Statistics - **Stars**: 0 - **Forks**: 0 - **Created**: 2026-09-09 - **Last Updated**: 2026-09-11 ## Categories & Tags **Categories**: Uncategorized **Tags**: None ## README # dsh-autoflower 流程动画插件(DeepSeek Harness)—— 上传流程图图片或录入文字流程说明,AI 识别后自动生成 **≤10 秒**的流程动画;背景(图片/纯色)、标题、角标可自定义;一键导出**高清视频**(WebM 1080p 起)。 ## 功能 | 能力 | 说明 | |------|------| | 🧭 动态流程图 GUI | 侧边栏底部「🧭 动态流程图」入口:全屏工作区,统一录入框(文字 + 附图)与任务条在左、动画渲染在右;渲染区底部控制条常驻(最左 = 播放/循环/缩放,最右 = 📥 导出 视频·图片);顶栏「← 返回 DSH / ❓使用说明 / ⚙️设置 / 📋 历史」 | | 🖼 图片流程图 → 动画 | 上传流程图/架构图图片,AI 读图识别节点/连线/文字并重建为矢量动画(非图图片会礼貌说明)。图片识别**自动**按原图网格保真(模型只判行列 → Host 算自适应坐标、对齐、修连线吸附侧)+ **自动**二次视觉校验,明细见 AI 回复的「▾ 识别结果」 | | 📝 文字 → 动画 | 录入文字流程说明,AI 解析语义自动生成流程动画(判断分支带是/否);一句话需求(如"帮我生成 SpringBoot 项目的网络拓扑架构图")由 AI **先设计组件再自动成图**(流程=flow / 架构拓扑=topo) | | 🧭 意图识别与普通对话 | 先判断内容能否构成图:问候/闲聊等无法成图的输入,AI 按普通对话答复,**不会**生成虚假任务;校验失败的模型自动**自愈重试一次** | | 💬 对话微调 | 识别错了、改文字、调流程,直接在左侧对话区描述,AI 修正后右侧即时更新 | | 🔄 AI 自我校验 | 识别后自动校验:①流程逻辑(开始/结束、边方向、判断分支、无孤立节点);②图片文字准确性(乱码/错字/相似字误读),发现问题先修正再渲染 | | ✨ 动画效果 | 节点按拓扑序点亮、连线逐条绘制、光点沿流程流动(GSAP 时间轴,≤10s) | | 🧩 语义图标节点 | 结构化为每个语义明确的节点标注 `icon`(database/cache/mq/gateway/registry…);画布用 **Path2D 内嵌矢量图标**渲染:带图标节点 = 圆角卡片「左侧真实图标 + 右侧文字」,数据库/MySQL 等不再画成平行四边形;即使 AI 漏标,label 含关键字也会自动兜底补图标 | | ↔️ 直线连线 | 连线全程直角且吸附锚点与折点严格同列/同行,修复 io(平行四边形)类节点的贴边微折 | | ✋ 节点可拖动 | rebuild 图上直接拖动节点微调:连线实时跟随吸附点并自动正交重路由(绕开其它节点);坐标自动落盘 `.dsh-autoflower/.json`(删除任务才清理),重开/回放保持你的布局 | | 🎯 连线可编辑手柄 | 点击连线显示手柄(直线=首尾 2 个圆点;折线=首尾+每个折点方块);端点可拖动到**其它节点**吸附点跨节点重连,折点可拖动并持久化 `waypoints`;hover 高亮、就近自动吸附,非法重连自动回滚 | | 🔗 新建/删除连线 | 工具栏「🔗 连线」开关后节点四边显示锚点:从一个锚点拖到另一节点锚点**自动新建连线**(同轴=直线,需绕行=自动折线,端点吸附);选中连线按 Delete / 工具栏「🗑 删除连线」删除(结构非法自动回滚) | | 🎨 定制 | 背景(纯色/图片)、标题、四角角标 | | 📤 高清导出 | 导出最终成型图片 PNG,或高清视频 WebM(MediaRecorder 录制,默认 1920×1080@30fps,可配 2K/4K、60fps、码率) | | 💾 持久化 | FlowModel 落盘 `<工作区>/.dsh-autoflower/.json`,可回放复用 | ## 架构 ``` Host (Node) Client (浏览器) ┌──────────────────────┐ ┌──────────────────────────────┐ │ flow_render 模型工具 │◄────────│ tool.call.toolview (key=flow_render) │ /autoflower RPC │ fetch │ grid→自适应布局(无 grid 用 dagre)→ canvas+GSAP │ FlowStore(内存+落盘) │ │ 「动态流程图」GUI(Vue3+Element Plus) │ AI 识别/微调(LLM) │ │ 输入/对话微调/渲染/设置/导出 └──────────────────────┘ └──────────────────────────────┘ ``` - **Host**:`src/index.js`(装配)+ `src/tools.js`(工具)+ `src/rpc.js`(RPC)+ `src/store.js`(校验/存取/落盘)+ `src/core/config.js`(配置)+ `src/core/flow-schema.js`(kind 语义域)+ `src/core/prompts.js`(固定格式提示词与信封契约)+ `src/services/ai.js`(AI 识别/意图路由/微调,OpenAI 兼容直连或回退 DSH 默认模型) - **识别 → 结构化 → 渲染 三层**:L1 识别层(意图路由:成图 `graph` / 普通对话 `chat`,图片/流程/一句话需求三种入口)→ L2 结构化层(固定信封 JSON → FlowModel,`store.validate` 按 `kind` 校验 + 失败自愈重试一次)→ L3 渲染层(`flow_render` 工具 / GUI 画布,只消费 FlowModel、不感知语义) - **Client**:`frontend/`(vite 双构建:dagre+gsap 引擎 + Vue3/Element Plus GUI)→ 构建产出 `client.js` - **组件复用**:dagre(自动布局)、GSAP(动画时间轴)、原生 MediaRecorder(高清录制);ffmpeg.wasm 因上游维护停滞未采用 ## 开发与发布 ```bash # 1) 安装前端依赖 + 构建 Client 端(dagre + gsap + 引擎 + Vue GUI → client.js) cd frontend && pnpm install && npm run build && cd .. # 2) 发布链(推荐):重建 client.js + 全量验证(engine-geom、check-client、tool-schema-check、host、index-smoke、security)+ 结构自检 node release.mjs # 3) 一键发布到 DSH:release(构建 + 验证)→ sync-to-dsh(覆盖 web profile 副本) node builder.mjs # 4) 首次安装 / 改代码后快速同步副本 node install-to-dsh.mjs # 默认 web profile(写入 dependencies + bundles + pnpm install) node sync-to-dsh.mjs # 快速同步副本(无需重新 pnpm install) # 5) 重启 DSH + 浏览器 Ctrl+F5 硬刷新 ``` ## 使用 **方式一:打开「动态流程图」界面**(侧边栏底部入口) 1. 左侧录入框:输入文字(流程步骤,或一句话需求如"帮我生成 SpringBoot 项目的网络拓扑架构图";回车换行,Ctrl+Enter 发送)或附图(🖼 / 拖拽 / Ctrl+V,PNG/JPG/WebP ≤4MB)→ 点「发送」识别为**新任务**并自动选中,右侧立即渲染 ≤10s 动画;问候/闲聊等无法成图的输入,AI 仅作普通答复、不生成任务;再次发送时若仍选中任务,按钮自动变为「**微调**」; - **图片识别自动保真 + 自动校验(无开关)**:模型只判「第几列/第几行」(`grid:{col,row}`),Host 按自适应网格算坐标(列=该列最宽+gutter、行=该行最高+gutter、按图片宽高比校正)、严格对齐、消重叠、修正与主轴冲突的连线吸附侧;再由视觉模型对照原图核对一次结构/连线方向(失败不阻断)。识别/微调结果只推一条 AI 回复,点下面的 **`▾ 识别结果`**(默认收起)可看几何指标、节点/连线清单与 FlowModel JSON;不满意可直接在画布拖动节点(自动落盘)。机制细节见 `DESIGN.md §3.1`; 2. 点选录入框下方「任务」条(或顶栏「📋 历史」)中的任务可**切换微调目标**(再点取消);识别/微调结果都落盘为工作区任务(`.dsh-autoflower/`),两处列表为同一份数据、选中互相同步;「🆕 新建流程」清空输入回到「发送」;删除任务(任务 ✕ / 抽屉 🗑)= 物理删除磁盘 JSON 与导出视频; - 图片识别模型回退链:插件设置中「图片识别视觉 LLM(直连)」→ 自动发现部署内支持图片的模型(如 llm-pi-ai 的 qwen 系列)→ 默认模型;都没有时给出中文提示; 4. 顶栏「❓」查看使用说明,「⚙️设置」配置图片识别视觉 LLM(直连)/ 入口位置 / 导出参数;「📥 导出 ▾」在**渲染区控制条最右端**(左侧为播放/暂停、循环、缩放等),可导出 **WebM 高清视频** 或 **最终成型 PNG 图片**。 **方式二:直接在对话里用 flow_render 工具**(不打开界面) ``` 把这段话做成流程动画:用户下单 → 校验库存 → 库存不足则提示缺货,充足则扣减库存 → 生成订单 ``` 或上传流程图图片,让 AI 识别后转成动画。动画会直接渲染在 `flow_render` 工具卡片中,可播放/暂停/重播/循环;非扫描(rebuild)图可直接在卡片画布上**拖动节点微调位置、从一个节点边缘锚点拖到另一节点新建连线**,改动经 `flow.update` 原位自动保存到该任务。点「导出高清视频」或「导出图片」得到 WebM/PNG 文件。 ## FlowModel 数据结构 ```jsonc { "kind": "flow", // flow(业务流程,默认)| topo(架构/拓扑/组件关系) "nodes": [{ "id": "n1", "label": "MySQL 主从", "shape": "io", "icon": "database", "pos": { "x": 120, "y": 80 } }], "edges": [{ "from": "n1", "to": "n2", "label": "是" }], "mode": "rebuild", // rebuild | scan(原图扫描光效) "title": "流程标题", "direction": "tb", // tb | lr "background": { "type": "color", "value": "#0f172a" }, "badges": [{ "text": "V1.0", "corner": "tr", "bg": "#ef4444", "color": "#fff" }], "animation": { "durationMs": 8000, "loop": true }, "export": { "width": 1920, "height": 1080, "fps": 30, "bitrateMbps": 8 } } ``` 约束:节点 2~20 个;时长自动 clamp 到 ≤10s;`flow`:开始/结束节点、判断分支必须带 是/否、非 end 节点必须有出口; `topo`:只保留单向 上游→下游 依赖(禁回边/双向成环)、叶子存储组件(MySQL/Redis/MQ 等)可无出口连线、无孤立/不连通子图、有入口根节点(shape=start)。旧数据缺省 `kind` 自动按 `flow` 处理。 节点可选填 `icon` 语义图标(database/cache/mq/gateway/registry…,见 `src/core/flow-schema.js` 的 `ICON_KEYS`),带图标节点渲染为「左侧真实图标 + 右侧文字」的圆角卡片;连线折点与吸附锚点严格同列/同行(无贴边微折)。 节点还可选填 `pos:{x,y}`(画布拖拽后持久化的逻辑坐标):**全部节点都有 pos 时渲染走手动布局**(坐标原样 + 正交重路由,重开/回放保持你的摆布);否则首次渲染后自动把 dagre 布局坐标落盘一次,之后即可继续拖动微调。 `edge` 可选 `srcSide/dstSide`(`top|bottom|left|right`)与 `waypoints:[{x,y}]`:画布**点击连线**显示手柄(首/尾圆点 + 折点方块),折点可拖动并持久化;端点可拖到**其它节点**四边红色吸附点实现跨节点重连(结构非法会自动回滚)。箭头始终按"进入目标锚点的走向"指向。 节点可选填 `w/h`(画布缩放持久化,分别 clamp 到 60~640 / 40~480)与 `image:{mime,src}`(对象节点图片,**仅 data:image/\*,≤2MB**,其余值由 Host 剔除)。 `background.src` / `originalImage` 只接受 `data:image/*`(≤2MB)或**工作区内**图片文件路径(扩展名 + 文件头校验);远程 URL 会被拒绝(见「🔐 安全边界」)。 节点 `id` 不得使用 `__proto__` / `constructor` / `prototype`;时长与导出参数超限由 Host 自动 clamp。 ## 🔐 安全边界 插件在 DSH 内以「本地 Web 服务 + 静态客户端」形态运行,`/autoflower/*` 是**同源浏览器接口**,因此按本地服务的安全基线实现(详见 `test/security.test.mjs` 的 28 项回归): | 边界 | 规则 | |------|------| | 传输协议 | 仅接受 `POST` + `Content-Type: application/json`;`GET/PUT...` → 405,非 JSON → 415 | | 来源校验 | 带 `Origin`/`Referer`/`Sec-Fetch-Site` 的请求必须与本机同源/同站,否则 403(挡 CSRF / DNS rebinding);无来源头的本机 CLI/脚本放行 | | 路径穿越 | `flowId` 只允许 `[A-Za-z0-9_-]{1,40}`(读/写/删全部校验),`cwd` 必须是「非磁盘根目录的路径」;数据只落在 `<工作区>/.dsh-autoflower/` 下 | | 图片来源 | 仅接受 `data:image/*`(≤2MB)或**工作区内**图片文件(扩展名 + 文件头双重校验,≤2MB);`http(s)/file/` 等远程或伪协议 URL 一律拒绝(防 canvas 污染导致导出失败 + 对外请求)。放宽:环境变量 `AUTOFLOWER_ALLOW_ANY_IMAGE_PATH=1` | | 节点图片 | 仅 `data:image/*`(≤2MB),其余字段直接剔除 | | 设置写入 | 服务端白名单 + 范围校验:`ui.entrySlot` 枚举、`export.width/height/fps/bitrate` clamp/enum、`llm.baseUrl` 必须 http(s) URL、`apiKey` 掩码 `****`/空串不覆盖已存 Key | | 敏感数据 | 配置文件 `~/.dsh/autoflower/config.json` 以 `0600` 落盘,对外一律脱敏(`apiKey: '****'`) | | 落盘 | 原子写(临时文件 + rename),异常不留半截 JSON/视频;`videos` 扩展名白名单、`images` 必须是真 PNG、请求体 ≤64MB | | 打开文件 | `flow.reveal` 只允许插件数据目录内已导出的视频/图片 | | 识别排障 | 多次自愈仍失败时,模型原始输出(截断 4KB,最多 20 份)落在 `<工作区>/.dsh-autoflower/_failed/`,不进历史列表 | ## **升级步骤**:`node install-to-dsh.mjs`(登记 `dsh-autoflower` 到 profile 的 dependencies + bundles)→ 完全退出并重启 DSH → 浏览器 Ctrl+F5 硬刷新。 (当前插件依赖 **Node ≥18 / pnpm 11**;前端依赖安装:`pnpm --dir frontend install`。) ``` plugins/dsh-autoflower/ ├── DESIGN.md 设计文档(含组件选型论证;0.3 已同步实施差异) ├── package.json 插件 bundle 声明 ├── cordis.patch.yml 挂载行 ├── client.js 构建产物(勿手改,需提交) ├── .gitignore 忽略 node_modules / dist / .dsh-autoflower 运行时数据 ├── install-to-dsh.mjs 一键安装到 DSH profile ├── sync-to-dsh.mjs 快速同步副本 ├── release.mjs 重建 client.js + 全量验证 + 结构自检 ├── builder.mjs 一键发布(release → sync) ├── src/ Host 端(工具/RPC/存储/AI) ├── frontend/ Client 端(vite 工程) ├── script/ 图标抓取等一次性脚本 └── test/ 测试防线(engine-geom / check-client / tool-schema-check / host / index-smoke / security) ```