☰
WAS Node Suite 配置指南:config.yaml 全键解析、文件布局、路径隔离与功能开关
2026/10/14 3:08:20 网站建设 项目流程
  • AI 应用
  • 图像处理

【免费下载链接】was-node-suite-comfyui

WAS-NS v3 Reborn; Tools for image processing, filters, masking, text, logic, numbers, latents, files, 3D scenes, and animation.

项目地址:https://gitcode.com/gh_mirrors/wa/was-node-suite-comfyui
点击查看免费下载

本指南以 WAS Node Suite(WAS-NS)的官方配置参考文档 docs/CONFIG.md 为核心,结合仓库内 modules/config 的源码实现,系统讲解配置文件从何而来、如何被解析与升级,以及version、logging、paths、text、document、history、video、interface、threejs、viewer、features、legacy、nodes每个配置块的每一个键。读完本文,你将能独立完成 WAS Node Suite 的首次安装配置、自定义路径与权限边界、按需开关功能组与旧版节点,并理解每次版本升级时配置文件的自动迁移机制。


配置文件从哪来:查找顺序与生命周期

WAS Node Suite 的配置文件首次启动时自动生成,并且存放在插件包之外(ComfyUI 的user/目录下),因此更新或重装插件都不会动到你的配置。仓库根目录下的 config.example.yaml 只是模板:它列出全部键及其默认值,注释里明确写着 "THIS IS THE TEMPLATE, NOT YOUR CONFIG FILE"——直接编辑它不会产生任何效果。

启动时,插件按以下顺序查找配置文件(对应 modules/config/paths.py 中find_config_file()的实现):

顺序位置说明
1$WAS_CONFIG指向配置文件的完整路径。如果该值不是一个文件,会被记录到日志并跳过
2<user_dir>/was-node-suite/config.yaml常规位置。<user_dir>即 ComfyUI 自己的user/目录
3插件自身__init__.py旁边的config.yaml在ComfyUI/custom_nodes/was-node-suite-comfyui/中读取;干净重装后会丢失
4内置默认值上述文件未设置的任何键都使用内置默认值。config.example.yaml以默认值形式列出了每一个键

除了config.yaml,config.json也同样被接受,且永远不会被插件重写(见 reconcile.py:JSON 文件没有可保留的注释,也没有可套用的模板,因此只读取、不重写)。

两个环境变量直接改变配置与状态的位置:

变量作用
WAS_CONFIG要读取的配置文件完整路径,优先于其他所有候选
WAS_CONFIG_DIR把整个was-node-suite目录(配置文件与可写状态)一起迁移到别处

从源码看,config_directory()的实现是:$WAS_CONFIG_DIR优先,否则回退到<user_dir>/was-node-suite(modules/config/paths.py)。值得注意的是,当进程不在 ComfyUI 环境下(folder_paths不可导入)时,user_directory()会回退到平台的数据目录(Windows 的LOCALAPPDATA、Linux 的$XDG_DATA_HOME或~/.local/share),此时插件只读不写(modules/config/init.py)。

配置目录里的每一个文件

配置目录(<user_dir>/was-node-suite)内除config.yaml外还存放着一组可写状态文件:

文件或目录存放内容
config.yaml本配置本身
was_state.db自定义文本 tokens、节点游标、图像/文本文件/输出图像历史、样式库(style library)以及 Noodle Soup Prompts 术语表
was_suite_settings.json首次启动时读入was_state.db,之后不再写入
was_history.json首次启动时读入was_state.db,之后不再写入
styles.json每次文件变化时导入样式库。从不被写入
nsp_pantry.json首次启动时读入was_state.db,之后不再写入。可选:术语表随插件自带,没有该文件也能初始化数据库
wildcards/通配符.txt文件(除非paths.wildcards指定了别的目录)
cache/Cache Node写入的文件(当legacy.cache开启时)

源码层面,modules/state/store.py 定义了数据库文件名DB_FILE = "was_state.db"与四个 store:settings(设置、自定义 tokens、节点游标)、history(历史列表)、styles(提示词样式库)、nsp(Noodle Soup Prompts 术语表)。文档特别指出:was_state.db是一个 SQLite 文件,两个指向同一配置目录的 ComfyUI 实例可以安全地共享它——store.py 为此实现了 10 秒写锁等待、8 次重试与退避等并发保护。旁边的四个.json文件只在首次启动时读入数据库、之后绝不写入,因此它们始终保持着"状态迁入数据库那一刻"的副本。

每次发布都会自动升级你的配置文件

每个版本发布时,插件会从模板把你的配置文件更新到最新:新键以默认值到达、退役的键被移除,而原文件被原样保留在旁边,命名为config.yaml.bak。你设置过的值永远被保留。该机制的实现位于 modules/config/reconcile.py 的reconcile():它以config.example.yaml为模板"渲染"新文件(保留注释与排版),写入前先copyfile生成.bak,并在日志中逐条报告added/removed/kept等操作。

对于features:组,升级逻辑更精细——因为磁盘上没有任何记录能区分"用户主动选择的值"与"系统写入的默认值",所以它用写文件那个版本的默认值来对照(见 defaults.py 的SUPERSEDED_FEATURE_DEFAULTS,按版本号记录了每个features.*的历史默认值):

你的features:组持有重写时会发生什么
当初被赋予的默认值顺延为本版本的默认值,并在日志的turned on/turned off下列名。若两个版本的默认值相同(大多数组在大多数时候如此),则没有变化,也不记日志
任何其他值原样保留,并在日志的kept下列名
什么都没有(键不在文件中)该键以本版本的默认值从模板到达,并在日志的added下列名
手写了一个该版本 schema 中不存在的组的值原样保留,且不记日志——因为没有默认值可用来识别它

迁移只运行一次:stamp_version()会把当前版本号写回文件,下次启动即视为已迁移(reconcile.py)。此外,v2 时代的was_suite_config.json也会在首次启动时被一次性迁移到 v3 schema(modules/config/migrate.py),旧文件保留不动,若干过时键(如ffmpeg_bin_path、use_legacy_ascii_text、SAM 权重 URL 等)会带着原因被记录并丢弃。


version

KeyTypeDefault
versionint16(当前仓库模板值)

由插件写入。修改它会改变"你的文件与哪个版本的默认值做比较"——即决定reconcile()用SUPERSEDED_FEATURE_DEFAULTS中的哪一条记录来判定features.*是否仍持有旧默认值。需要说明的是,docs/CONFIG.md 表格中记录的默认值为13,而仓库当前模板 config.example.yaml 与 defaults.py 中的VERSION = 16;版本号随每个发布递增,数值本身不代表任何能力,只是 schema 修订标识。


logging

KeyTypeDefault作用
logging.leveldebug|info|warning|errorinfo插件自身 logger 允许输出的最低级别。debug会额外输出依赖探测、模型解析、缓存驱逐、各模块加载耗时,以及被禁用的节点组挡掉的节点 id
logging.richbooltrue当rich已安装时输出彩色日志。未安装或设为false时回退到普通流式 handler
logging.quotesboolfalse被接受但没有效果:没有任何节点或 loader 会打印引语

源码实现位于 modules/log.py:configure()以LEVELS映射把字符串级别翻译成标准库级别(无法识别的值一律按info处理),rich=True时优先尝试构造RichHandler,失败则回退到带[WAS Node Suite]前缀的StreamHandler。所有模块的 logger 都挂在was_node_suite根名下(如was_node_suite.config、was_node_suite.image.filters),便于统一过滤。


paths

KeyTypeDefault作用
paths.wildcardspath 或nullnull通配符.txt文件目录。null表示<user_dir>/was-node-suite/wildcards
paths.stylespath 或nullnull要导入的样式库。一个.json文件或 Automatic1111 的styles.csv会在每次文件变化时被读入样式库,从不被写回。样式库中该文件从未命名过的样式会被保留。null表示<user_dir>/was-node-suite/styles.json
paths.lutspath 或nullnull.cube颜色查找表目录,也是Save LUT的写入位置。null表示<user_dir>/was-node-suite/luts。无论这里指向哪里,ComfyUI 的models/LUT都会在其后继续被读取
paths.allow_read路径列表[]额外允许节点读取的目录。见下文"路径隔离"
paths.allow_write路径列表[]额外允许节点写入的目录。见下文"路径隔离"

模板中还包含一个 CONFIG.md 路径表未列出的键paths.scratch(默认null):帧批次大到内存放不下时,用于落盘的文件夹;null时使用 ComfyUI 的temp/(config.example.yaml,defaults.py)。

两个没有配置键的文件夹:

  • Image Draw Text从<user_dir>/was-node-suite/fonts读取字体,与插件自带的九个字体并存;放入该目录的.ttf或.otf会在重启后出现在font菜单中。便携版 Windows 安装下该路径为ComfyUI_windows_portable\ComfyUI\user\was-node-suite\fonts。
  • App Workflow会列出<user_dir>/default/workflows/下(含子文件夹)所有*.app.json文件。

路径书写注意事项(模板注释与 defaults.py 的WINDOWS_PATH_FIX都在强调):

  • 每个路径设置中的~都会被展开。
  • 相对路径相对于进程工作目录解析,而 ComfyUI 的工作目录并不稳定——强烈建议使用绝对路径。
  • Windows 路径在 YAML 双引号内写反斜杠会触发转义序列,应使用正斜杠或单引号,例如'D:/prompts'。解析器在遇到含反斜杠的错误行时,会在警告中直接给出这条修复建议(modules/config/init.py)。

加入allow_read/allow_write后目录如何出现在菜单

加入allow_read的目录会以它自己的名字出现在每个文件和文件夹菜单中,其文件在括号里携带该名字,例如D:/photos显示为photos,其中文件显示为sunset.png [photos]。加入allow_write的目录以同样方式出现在每个root菜单中。文件夹菜单只列三层深、最多 2000 条。修改任一列表后需要重启 ComfyUI。

从 modules/io/rooted.py 的源码看,写菜单的根依次是:节点自带的额外目录 → ComfyUIoutput/、temp/→paths.allow_write中的目录;读菜单则依次是:节点自带目录 → ComfyUIinput/、output/、temp/→paths.allow_read中的目录。配置目录的 basename 会被清洗成菜单名(非字母数字字符替换为-),重名时自动追加-2、-3等后缀。


路径隔离(Containment)

当一个节点的输入命名了文件或目录时,该路径在触碰文件系统之前就会针对以下根目录进行解析。落在所有根目录之外的路径会被拒绝,且不读取也不写入任何东西:

读写
ComfyUIinput/是否,写入会被转移到temp/(见下)
ComfyUIoutput/是是
ComfyUItemp/是是
插件自身目录<user_dir>/was-node-suite/(或$WAS_CONFIG_DIR)是是
paths.allow_read中的任何目录是否
paths.allow_write中的任何目录否是

隔离机制的核心实现在 modules/util/sandbox.py 的_resolve(),其行为与文档完全对应:

  • 子目录:允许的根目录的子目录同样被允许。
  • input/写入重定向:解析后落在input/内的写入会被改写为temp/下相同的相对路径,并在日志中同时记录两个路径。源码注释解释得很清楚:input/存放上传内容,temp/本身是合法写根,且会随一次运行的临时数据一起被清理(sandbox.py)。
  • 完整解析后再比较:比较双方都会被完全解析(resolve()),这覆盖了..段与符号链接——根目录内指向根外部的符号链接不会扩大边界(contains()会拒绝它,见 sandbox.py)。
  • Windows 上比较不区分大小写;每个条目必须是已存在的目录,否则会被丢弃并告警。
  • 除上述根外,store.py 中还有一层自我保护:config.yaml、config.json与viewer-extensions目录属于PROTECTED,任何节点都不得写入(sandbox.py)。
  • 拒绝消息:拒绝时会给出路径、每一个允许的根目录、以及"哪个键本可以允许它"(Add the directory to paths.allow_read in config.yaml to permit it.,见 sandbox.py)。

text

KeyTypeDefault作用
text.strip_commentsbooltrue为多行文本的注释剥离保留,但注释处理并不读取它:Text Multiline总是丢弃首个非空白字符为#的行,而Text Multiline (Code Compatible)从不这样做。把它设为false不会有任何变化

也就是说,这是一个"保留但当前无效果"的键,模板注释同样写明了这一点(config.example.yaml:"reserved; comment handling does not read it")。


document

KeyTypeDefault作用
document.clean_htmlbooltrue移除文档节点输出的 HTML 中的 script 与 frame 标记。具体删什么、留什么,见下表

开启后移除以下内容,除此之外不碰任何东西,节点上文本框里的原文也从不被重写:

被移除的其中保留的
<script>元素无——标签及其间所有内容全部移除
<iframe>元素无——标签及其间所有内容全部移除
<object>与<embed>标签标签之间的所有内容,即嵌入加载失败时读者看到的 fallback
所有名称以on开头的属性,如onclick、onerror元素本身及其文本
href、src、action、formaction、data、poster、cite、ping、background、longdesc、srcset或xlink:href中的javascript:元素本身及其文本,因此带脚本的链接会变成纯文本

文档同时给出了明确的边界声明:它只清理你自己机器上写出的标记,不是针对不可信页面的强化消毒器(hardened sanitiser)。

Rich Text Editor 的固有规范化(不可关闭)

Rich Text Editor会把它收到的内容解析成文档再写回,因此标记会在往返过程中被规范化。以下重写都不是document.clean_html做的、都不能被关闭、并且作用于交给编辑器的每一个文档:

会发生什么你拿回什么
schema 不接受作为 body 子节点的顶层节点被包进段落Hello读回<p>Hello</p>。独立存在的<iframe>、<object>、<textarea>、<input>、<math>或未知元素也是如此
schema 不允许出现在当前位置的元素会被解包、移位或给予它需要的父节点<td>a</td>读回<p>a</p>;<li>a</li>读回<ul><li>a</li></ul>;<table><tr><td>x</td></tr></table>会补上<tbody>;<div>内的<body>被解包
五个字符被写成实体:文本中的<、>、&,以及属性值中再加上"与反引号<p>AT&T</p>读回<p>AT&amp;T</p>;<p>5 < 6</p>读回<p>5 &lt; 6</p>;title='a"b'读回title="a&quot;b"。撇号不在这五个之内
所有其他实体被解码为其字符再写回&copy; &eacute; &#169;读回© é ©;&nbsp;读回字面意义上的不换行空格。&amp;amp;会存活:它解码为&amp;再重编码为&amp;amp;
文本中的空白被折叠文本中的 tab 或换行变成空格,连续空格并成一个:<p>a b</p>读回<p>a b</p>。块之间的空白被丢弃而非折叠,文档两端的空白被修剪。<pre>内的空白不受影响
HTML 标签与属性名统一小写,属性值统一双引号<DIV CLASS=x>a</DIV>读回<div class="x">a</div>。SVG 保留其驼峰写法:<linearGradient>原样保留
空元素(void element)去掉 XHTML 斜杠<p>a<BR/>b</p>读回<p>a<br>b</p>
style属性被重新解析并重新序列化style="font-weight:700; COLOR:#ABCDEF"读回style="font-weight: bold; color: #abcdef;";url()无论原来用什么引号,都被重写为单引号
若style声明包含url()中的javascript:、vbscript:或data:image/svg+xml,或是behavior,或包含expression()或 CSS 注释,则被丢弃;因此被清空的style属性一并移除style="color:red;background:url('javascript:go()')"读回style="color: red;";style="background:url('javascript:go()')"整个属性消失
<svg>后代上的on*属性被删除<svg><circle onload="go()" r="4"></circle></svg>读回<svg><circle r="4"></circle></svg>;嵌套的<a onclick>与<foreignObject>内的<div onclick>同样被处理
布尔属性被重写为name="name",schema 有默认值的属性会被补上disabled=""读回disabled="disabled",裸checked读回checked="checked",<input name="a">会补上type="text"
文档、head 或 metadata 元素被丢弃<!DOCTYPE html><html><head><title>t</title></head><body><p>x</p></body></html>读回<p>x</p>。<style>块无论在哪都会被移除,<link>、<meta>同理
CDATA 段或 XML 处理指令不被当作标记读取(这正是 HTML 的行为)<![CDATA[raw & <stuff>]]>读回<![CDATA[raw & <stuff]]><p>]]&gt;</p>;<?xml version="1.0"?>读回<!--?xml version="1.0"?-->
空块会获得<br>;整个文档只是空段落时返回空字符串<p></p>读回<p><br></p>,<div></div>读回<div><br></div>,单独的<p>&nbsp;</p>读回空
内部data-mce-*属性被移除<p>
  • AI 应用
  • 图像处理

【免费下载链接】was-node-suite-comfyui

WAS-NS v3 Reborn; Tools for image processing, filters, masking, text, logic, numbers, latents, files, 3D scenes, and animation.

项目地址:https://gitcode.com/gh_mirrors/wa/was-node-suite-comfyui
点击查看免费下载
上一篇:BlockNote 项目中的 playwright-cli run-code 高级自动化指南:从浏览器上下文操作到复杂工作流
下一篇:Diffusers 中的 NVIDIA Cosmos 3 全模态世界模型:Cosmos3OmniPipeline 生成、动作条件与多卡并行推理实战指南

创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询