一块能自己跑起来的画布:把节点连起来,图就开始执行;改一个参数,只有受影响的那条链重算。
怎么长出来的
它的 git 仓库只有一次提交(2026-09-15 初始化),没有可供追溯的历史,所以演进只能从文档里带日期的条目读。
而那些条目挤在 9 月 3 日和 4 日两天里,一条接一条:
- P0–P3:脚手架、核心数据模型、交互闭环、执行引擎,文档同步建立
- P4 能力接入:Canvas 2D 的媒体处理、图像输入/滤镜/缩放/显示节点、节点内实时预览,以及第一条 AI 生成链路(
ai:image节点 + 配置面板) - P5 产品化:自动保存与 JSON 导入导出、ELK 自动布局、斜杠命令、Agent 技能接入层
- 执行引擎修复:三个真 bug —— 就绪判定误用出边导致顺序颠倒、缓存命中未移出 pending 导致 worker 死循环、参数修改没触发重算
- 收尾:单测、E2E 回归、300 节点压力测试、本地 AI 模拟服务、Agent 技能网关
- 9 月 4 日:照着一份界面截图做了整轮视觉改造 —— 画布压到近黑、卡片改深灰实底、标题移到卡片外部
往下还有 MCP Server、浮动面板、明暗主题、AI 生图流程完善等等,都是同两天的条目。
这个仓库还是 weave 的前身:
docs/WEAVE-HANDOFF.md就是 weave 的立项交接包,写明「同技术栈、借鉴经验、不迁移任何代码」。
和主线的结合点
我的主线是「探索面向 AI 的交互边界」。这块给出的答案,和另外两块都不一样:
| 作品 | AI 的位置 |
|---|---|
| Zifo | 流程外 —— 离线跑一遍,产物固化成 TTML |
| 无限画布白板 | 桌边同伙 —— 和人走同一条提交路径,可撤销 |
| 通用节点编辑器 | 管线里的一步 —— 一个节点,连上就跑 |
三种摆法里,这一种恰恰是我不偏好的那一种:节点是机器的一个零件,按确定的顺序被调度,不是同伙。
但它补上了缺口的另一半。 三条判据里,我一直说「能主动发起」还没捅穿 —— 意思是系统应该自己看见值得做的事,然后开口。这块作品已经做到了前半句:
- 加载即执行(打开页面,8 个节点自己跑完)
- 连接即运行(连上一条线就重算)
- 改参数即重算(改一个数字,下游自动更新)
都不用点任何按钮。 但驱动源是数据变化,不是 AI 的判断 —— 它不会“觉得”什么值得做,只会“发现”输入变了。
所以它精确的位置是:离「能主动发起」最近的一块现成骨架,缺的是判断力那一步。 这比三块都声称满足三条判据要诚实,也让这条主线看起来确实还在探索中。
难点
就绪判定看错了边。 调度器要判断一个节点能不能跑,得看它的入边前驱是否都完成。一开始看的是出边 —— 结果执行顺序整个颠倒,后面的节点先跑了。这个 bug 不是“偶尔出错”,是稳定地反向执行。
缓存命中之后忘了收尾。 加上跨运行缓存后,命中的节点直接复用输出、跳过执行。但漏了一步:它没有从 pending 集合里移出。于是调度器一直在等一个永远不会完成的节点,worker 空转成死循环。缓存做得越有效,这个 bug 触发得越频繁。
没有就绪节点时不能收尾。 并发调度有 4 个 worker。当队列暂时为空但还有节点在跑时,如果直接判定“执行结束”,就会在延时节点(比如 800ms)还没回来的时候提前宣告完成。这里必须等待而不是退出。
引擎和渲染必须解耦。 节点组件不持有执行状态,只读 state / progress / outputs;引擎回写这些字段来触发响应式更新。不这么分的话,节点自己一边跑一边改界面,执行状态和视图会互相拉扯 —— 这也是那三个 bug 都出在调度层、而没有出在组件层的原因。
亮点
跨运行缓存。 每个节点的缓存键是「自己的参数 + 上游输出」的哈希,存下来跨运行生效。实测:改一个数字输入后,8 个节点里只有 5 个重新执行,3 个被跳过 —— 未受影响的整条分支直接复用输出。而且这不是“少跑几个”的体感,执行栏会明写「缓存跳过 3」。
三种自驱,都不用点按钮。 加载即执行、连接即运行、改参数即重算。实现上是一个 watch 盯着「节点 id 集合 + 边 id 集合 + 参数版本号」,三者任一变化就重跑。参数版本号是专门为此加的 —— 最初的 watch 只监听结构变化,所以改参数不会重算,这是那个“第三个真 bug”。
引擎与渲染解耦。 引擎是纯 TypeScript,不依赖 Vue;节点组件只读状态。所以调度逻辑可以用 vitest 单独测(引擎 9 例 + store 8 例),画布怎么改都不会碰坏执行。
MCP 让外部 AI 自己搭图。 一个 stdio 传输的 MCP Server 暴露 8 个工具:list_nodes / graph_new / graph_add_node / graph_set_params / graph_connect / graph_list / graph_export / graph_clear。节点目录与应用内的注册表同构,所以 AI 连上以后可以自己把一张图搭出来、导出成 JSON,再导回应用里还原 —— 这条链路是验证过的。
1.4 MB 的布局库不进首屏。 ELK 自动布局用的是 elkjs,打包出来 1431 kB(gzip 442 kB)。它走动态 import(),只有点了自动布局才加载。实测首屏请求里没有它。
