Commit Graph

5 Commits

Author SHA1 Message Date
QAyong
9bc5512140 feat(portrait-clearance): 肖像排查 - 增加画布插件与本机检测链路 2026-08-26 15:23:19 +08:00
ddCat
2f3a813ccb feat(platform): 插件协议系统 - 支持声明式渠道、工作流与参考媒体映射 2026-08-26 13:11:10 +08:00
dlh
90d6c58de9 feat(canvas): 扩展节点 - 新增 7 种展示与加工节点并补齐上游读取基建
在已落地的节点注册表上加两层节点:展示层(Markdown / SVG / HTML / 全景)与
接入生成链的加工层(对比 / 图表 / 调色)。全部是第一方内置节点,不引入远程插件
加载,因此不涉及沙箱信任模型,也不需要把 CanvasNodeType 放开成任意字符串。

刻意保留穷尽性检查而不是改成运行时注册。全库只有 4 张按类型建的穷眉表
(NODE_DEFAULT_SIZE / NODE_SPECS / 注册表定义 / nodeContentRenderers),
让编译器强制每个新节点填满它们,比少改几个文件更值 —— 加第一个枚举成员时
编译器点出了 5 处,其中 pages/canvas/shared.tsx 是原先没编目的那一处;
换成运行时注册,那里会静默回落成「未知节点」。

两处前置基建:
- CanvasNodeGraphContext:渲染器只拿到 node、没有 connections,而加工层三个节点
  都要读上游。仿已有的 canvas-node-action-context(同一个问题:节点经
  CanvasProjectWorldLayers 渲染不便逐个透传),取上游复用
  canvas-resource-references 的 getContextResourceNodes,不另写一份。
  Provider 值必须 memo —— 每帧新对象会让所有节点跟着重渲染。
- ToolbarHandlers.onAddExtensionNode(type):一个泛用入口,不给每种扩展节点单开
  一个 onAddXxx。菜单另开「展示与加工」分区,不挤占上方调好的四列创作网格。

SVG 与 HTML 统一走 sandbox iframe:依赖里没有 DOMPurify,手写 SVG 消毒不可靠
(script / on* / foreignObject)。SandboxedFrame 只暴露 allowScripts 布尔而不是
sandbox 取值,让「同时给 allow-same-origin」这条没有入口。

全景节点三个取舍:点击才激活 WebGL(浏览器对同时存在的上下文有硬上限,画布可以有
任意多个全景节点,自动激活必然在某个数量后整片黑);用原生 three 而非 fiber
(需要精确 dispose,forceContextLoss 才真正释放上下文);性能模式下只给静态预览。

调色是唯一碰生成路径的节点,照 Drawing 的先例:拖滑杆只做本地 CSS filter 预览,
落地成资源要等到生成消费它时才走 uploadResourceFile。预览与导出共用同一个
filter 字符串,两处各写一份就会「看到的和用的悄悄不一致」;未调色时直接透传源图,
省掉一次渲染与上传。ctx.filter 不受支持时明确报错而不是导出一张没调色的图。

resourceKind 与 inputKind 分开两个字段:空图片节点不是素材(不进 @ 引用),
但照样计入 imageCount。调色节点的 resourceKind 无条件返回 image —— 它的图来自
上游,按「有没有 content」判断会让它永远进不了生成输入,这是不报错的静默失效。

测试:新增 test/canvas-extension-nodes.test.ts(12 用例 / 64 断言),覆盖 7 个节点的
判据矩阵、调色参数、以及图表解析。图表解析函数刻意不抛 —— 数据来自模型输出,
非法 JSON 是常态而不是异常,抛出来会连带整个画布白屏,有 7 条断言钉这个。
测试列表是显式枚举,已把新文件加进 package.json,不加进去不会跑。

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-08-22 12:29:24 +08:00
dlh
a4585fdc2a refactor(canvas): 节点注册表 - 收敛素材类型、生成模式与输入计数判据
把三条按类型分支的语义判据收进注册表:
- resourceKind  原 canvas-resource-references.ts,作为 @ 引用素材时的类型
- generationMode 原 canvas-connection-policy.ts,作为生成节点时的模式
- inputKind     原 canvas-connection-policy.ts,被容量校验计数时的类别

resourceKind 与 inputKind 刻意分成两个字段:它们语义不同——空图片节点不是素材
(不进 @ 引用),但照样计入 imageCount。合成一个会静默改掉连线容量校验。

两处必须保住的语义,均已由测试钉住:
1. 角色卡(workflowKind === character)是跨类型覆盖,对任何节点类型生效,
   属于查注册表之前的前置判定,因此留在调用点而不进 per-type 定义。
2. 排除必须早于覆盖。原实现先 return 掉生成配置与背板,之后才判角色卡;
   若把角色卡判定提前,带角色元数据的配置/背板节点会被多算成 characterCount。

新增 test/canvas-node-registry.test.ts(19 用例 / 77 断言)并加入 package.json
的 test 列表——该列表是显式枚举,不加进去文件不会跑。补测的原因是
canvas-resource-references.test.ts 只覆盖 collectUpstreamVideoNodes,
本次改动的 resourceKind 此前零覆盖,而这类判据出错不报错、只会让 @ 引用少收素材。

顺带内联 nodeGenerationMode(迁移后退化为单行转发)。

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-08-20 22:27:23 +08:00
dlh
af84cf5772 refactor(canvas): 节点注册表 - 收敛节点展示与几何知识到单一数据源
每加一种画布节点,叫什么、长什么样、能不能自由拉伸要在 4-5 处各写一遍。
实际后果是节点标签出现三份且互相矛盾(NODE_DEFAULT_SIZE.title / 创建菜单 label /
搜索弹窗 nodeTypeLabel),canvas-node-size.ts 里还有第四份硬编码兜底。

新增 lib/canvas/node-registry/,镜像现有 tool-registry/ 的结构:
静态定义带 satisfies Record<CanvasNodeType, ...> 做编译期穷尽性检查
(往枚举加成员不补定义即编译失败),再注册进模块级 Map 并按 ownerId 归属,
为后续扩展留出隔离位。

尺寸与初始 metadata 的数据源仍是 constant/canvas.ts 的 NODE_SPECS,定义文件读它
而非复制,现有约 40 处布局计算未动;渲染层 nodeContentRenderers 已是查表结构,
本次不改。

标签刻意分三个字段各司其职,界面文案零变化:
- defaultTitle 新建节点默认名(Note/Audio/未命名背板 原样保留)
- label UI 短标签
- listLabel 列表标签,缺省派生为 label + 节点;背板显式钉住为背板

接入 3 处调用点:创建菜单标签与图标、搜索弹窗类型标签、canvas-node.tsx 的
minWidth/minHeight 与 keepRatio。导演台落在节点分区但开的是工作台、不是节点类型,
故不走注册表。

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-08-20 22:22:28 +08:00