每次发布按版本记录变更。
Prompt Agent 补齐前台连接管理:API 连接可新建、编辑、复制、删除、检测和应用到当前节点;DSH 目录、Profile、Relay 可配置并扫描检测。区分 API 预设与 DSH 实时来源,保留每组连接自己的请求参数;多模型来源要求明确选择,删除不会自动换账号。检测只读模型列表,不提交计费生成。见 Agent 使用说明。
修复现代节点界面进入子图时自定义 UI 空白、切换工作流时残留旧面板的问题;统一恢复 Toolkit 的 DOM 控件,保留画廊悬浮窗挂载。输出文本框拖拽高度按节点保存到工作流,保存工作流后刷新与重新打开可恢复,兼容画布缩放。
多重画廊减少重复运行大图时的瞬时内存:原地执行 float32 归一化并关闭 PIL 解码资源,避免额外复制整张浮点图。4771×3096 实图第二轮额外分配峰值从 351.36 降至 224.58 MiB(约 36.1%),逐像素结果一致;保留原尺寸。该数字为图像解码的内存测量,不代表 GPU 加速或所有卡顿已解决;完整工作流连续两轮仍待复验。
组合发行版采用 GPL-3.0,并保留原有 MIT 授权与第三方署名;对应源码、锁文件、图标许可与构建说明随包提供。见 许可说明。
角色资料增量维护:可选每日使用时后台检查、缺失角色在线补查、来源/时间/错误状态、独立持久化与上一版备份;AnimaDex和Danbooru角色标签来源,数据提交后索引自动生效。保留随包底库、中文别名与用户数据。
Prompt Agent:源角色查库常驻开关(默认开启),看图扩写前为 WD14 角色提供本地人物候选与特征参考;查询缺失不阻断。Layout 连线扩写接入辅助 Skill,配置仅列出格式兼容的辅助规则。
data/lora_trigger_overrides.json,扫描和重新提取不会覆盖手动内容;不同目录的同名 LoRA 分开保存。画廊滚轮加载新一批图的时候,整屏会闪一下黑,加载完位置还会往上跳一段。这两个症状是同一个 原因:追加取数的时候,取数那层自己先渲染了一次,而那一刻手里只有刚取回的新一批,于是整个 网格被换掉,已经在屏幕上的图被清空重建(所以闪),滚动位置也被浏览器夹回了 0(所以跳)。
现在的做法:追加模式下取数那层只负责拿数据,渲染统一交给调用方收尾(失败和超时改成抛错, 免得被当成”到底了”而永久停手);渲染改成增量,只往网格里加新卡片,旧卡片和已经加载好的 图片原样留着,数据侧回收掉的开头几张也跟着从 DOM 删;滚动位置不再只记一个数字,而是记住 视口顶部那张图是谁、偏移多少,布局完成后按它还原。
web/js 改动,Ctrl+F5 刷新(不用重启 ComfyUI)。tests/test_gallery_infinite_scroll.py:追加取数不得中途渲染、增量路径不得清空网格
或断开懒加载观察器、对不齐时必须回退全量重建、锚点的记录与还原。「我的收藏」抢搜索框、抢计数标签额度。有用户反馈:”为什么收藏栏目是进搜索框,占用筛选词条,
导致显示不出来”。上一版把 ordfav:<账号> 写进了搜索框,问题有两个:一是它直接顶掉了用户
自己的筛选词;二是 FREE_METATAGS 里没有 ordfav,它就被当成普通计数标签参与
countedSearchTerms(),跟用户自己的标签抢那 2 个名额(Member 等级),超限后触发自动降级,
界面上就什么都显示不出来。
现在改成独立模式开关:点工具条「我的收藏」只切模式,搜索框一个字都不动,ordfav:<账号> 在
search() 发请求时自动拼在最前面,所以能和筛选词一起用(比如「我的收藏 + 1girl」)。同时把
ordfav 加进 FREE_METATAGS_THAT_STILL_COUNT(和 order 同级):D站 服务端确实算它一个
计数槽,限额判断就得如实算上,超限时给明确提示,而不是静默失败。按钮改成开关态(高亮就是
正在看收藏),换到别的图源自动退出这个模式。
web/js 改动,Ctrl+F5 刷新。tests/test_gallery_favorites.py 加了断言,钉住入口必须是模式开关、不得碰 queryInput、
ordfav 必须在计数集合里。D站 收藏读写(Issue #3「TK多重画廊收藏问题」:收藏了图片之后没有找到存放的地方)。 旧版卡片上那个收藏标记只是本地 localStorage 描边,全文件没有任何地方读它做筛选或排序, 按钮本身也在 2026-09-21 被移除了。所谓”找不到存放的地方”其实是结构性的。现在做成了真正写回 D站 账号的收藏:
POST /favorites,取消时先查出收藏记录 id 再
DELETE /favorites/<id>)。不做乐观更新,只有后端确认成功才改图标,不会出现”看着收藏了
其实没写进去”。写请求有连点保护,失败时把 D站 的原因(收藏上限、重复、权限)翻成人话显示
在状态栏。ordfav:<账号>。展示、分页、无限滚动、缩略图代理、
浮层全部复用既有的搜索链路,不需要另写一套渲染。按钮上直接显示收藏总数。logged_in:false,界面给”去登录”引导而不是一个红错误;写接口返回 401 加
可读提示。凭证只留服务端,任何响应都不含 api_key。设计上其实没什么花样:Danbooru 的收藏本质就是
ordfav:<login>这个计数标签搜索, 所以”看收藏”和”搜索”本来就是同一条链路,新增的只有”写”这一小块。
web/js、web/css 改动 Ctrl+F5 刷新;.py 改动本机已由 tk-hotreload 自动重载
(其它机器要重启 ComfyUI)。tests/test_gallery_favorites.py(10 条:真接口、记录 id、未登录引导、不泄露 key、
复用搜索链路、缓存失效、非乐观更新、换源清空、两个入口、主题变量)。page=1/2/3 返回完全相同的
id)—— 这是”加载不到新图片”的主因:前端在 pageMode() 分支发的是 page,而这三个源的
路由只读 cursor,每次都拿第 1 页,追加时全是重复,判定”到底了”不再请求。
修法:路由在 cursor 为空时回退读 page(moebooru 的 cursor 语义就是 1 基页码,直接等价;
safebooru 的 cursor 是 pid(0 基),回退时 pid = page - 1)。
同时回包补发下划线键 next_cursor(前端只读这个,此前只发驼峰 nextCursor,游标是死字段)。scroll 事件驱动加载,而内容没超出容器时根本不会产生滚动条,scroll 永不触发,
加载链启动不了(用户截图那种”一页 30 张、底部大片空白”正是这个状态)。
现在新增不依赖滚动事件的自动入口:scheduleScrollFill()(渲染收尾调用)→
autoFillByScroll() → 判据与滚动加载同源(scrollNeedsMore():剩余滚动距离 ≤ 600px)→
继续 appendNextBatch(),直到填满容器 / 上游到底 / 撞上硬闸(轮次上限 + 30s/4 批)。
自动补满链(scheduleAutoFill)在无限滚动模式下整条让位,两条链不会同时打上游。web/js 改动 Ctrl+F5,无需重启 ComfyUI。tests/test_gallery_infinite_scroll.py 新增「没有滚动条也要能启动加载」用例(10 passed)。画廊滚轮仍被画布抢走(用户实报:”滚动只会变成缩放画布比例,无法真正滚动”):
上一版只在 .adg-grid 上挂了 wheel + stopPropagation(capture),对 ComfyUI 无效。
查 ComfyUI 1.48.7 前端打包源码(assets/settingStore-*.js)后确认:判定发生在画布容器
上(Vue @wheel → handleWheel),条件是
wheelCapturedByFocusedElement = e => {
const t = e.target?.closest('[data-capture-wheel="true"]');
const n = document.activeElement;
return !!(t && n && t.contains(n)); // 两个条件缺一不可
}
shouldForwardWheelEvent = e => !wheelCapturedByFocusedElement(e) || isCanvasGestureWheel(e);
不满足就把 wheel 交给 forwardEventToCanvas() 做画布缩放。现在按官方约定实现:
网格打 data-capture-wheel="true" + tabIndex = -1,鼠标移入网格时聚焦它
(正在编辑输入框时不抢焦点,否则鼠标滑过画廊会把光标从提示词框里踢出去),
并补 .adg-grid:focus { outline: none } 避免多一圈描边。
Ctrl/Cmd+滚轮与横向滚轮仍归画布 —— 那是 ComfyUI 的画布手势白名单
(isCanvasGestureWheel),属官方语义,不是缺陷。
web/js、web/css 改动 Ctrl+F5 强刷即可,无需重启 ComfyUI。tests/test_gallery_infinite_scroll.py 的滚轮用例已改写为”必须走官方约定”
(钉住 data-capture-wheel + 可聚焦 + 移入聚焦 + 不抢输入焦点),防止再退回
“加个 stopPropagation 以为就好了”。wheel 拿去做缩放/平移了,现在在网格上拦截)。appendNextBatch()),不会同时打上游。大节点「底部大片空白、最右列稀疏」(用户实报):真根因是 gallerySearchParams() 对所有
页码分页源硬发 limit = 30,自适应张数完全不参与,节点越宽越填不满。现在只有 P站
保持 30(后端 page 换算写死 (page-1)*30),yande.re / konachan.net / safebooru
改按节点尺寸取自适应值(后端各自 clamp ≤100)。
离线复算(真实帖子宽高 + 同一套算法,判据同 gridUnderfilled()):
| 节点宽 | 列数 | 视口高 | 改前(limit=30) | 改后(自适应) | 再补一轮 |
|---|---|---|---|---|---|
| 780 | 6 | 800 | 89.4% | 114.1% | 191.2% |
| 1200 | 9 | 800 | 51.7% | 99.1% | 130.8% |
| 1580 | 12 | 800 | 35.8% | 71.1% | 89.3% |
| 1400 | 11 | 945 | 33.6% | 65.0% | 83.8% |
补图链「被拦下就永久停手」:请求在途 / 30s 窗口 / 用户拖过尺寸后的 1.5s 静默期, 原先都是「拦下即 return,没有任何重试」,撞上任意一道就永远停在半屏。 现在改为有界重试(拦下时按”还要等多久”排一次延迟重试),30s/4 批硬闸保持不变。
web/js、web/css 改动 Ctrl+F5 强刷即可,无需重启 ComfyUI。tests/test_gallery_infinite_scroll.py(8 条:两链共用取数 / 模式门控 / 滚动位置保持 /
分页器保留 / 上限回收 / 滚轮拦截 / 样式变量 / 自动补满让位)。separatorBefore),
而末尾分隔符不属于任何后续片段 —— splitPromptPieces() 在循环结束后对残余分隔符调
push(""),被判空丢弃,用户手打的尾逗号、①区联想补的 ", "、②区追加后的尾逗号,
只要经过一次 serializePromptPieces()(_commitPromptPieces / _ensurePromptPiecesInSync
都会走)就凭空消失。现在给最后一片段加 trailingSeparator(split / serialize / normalize
三处),并在 ①区 _applySuggest()、②区 _appendResolvedText() 里显式补尾逗号
(末尾是换行时不补,以免破坏多行分段)。web/js 改动 Ctrl+F5 强刷即可,无需重启 ComfyUI。tests/cards_widget_logic.test.js:尾逗号往返不丢 / 无尾分隔符不多补 /
末尾换行照旧保留 / 尾分隔符挂位)。anima_danbooru_gallery.py 的 get_selected_data()):
原先逐张串行,每张约 1 秒的固定开销(代理握手 / DNS+TLS / 首字节,与分辨率无关)被完整叠加。
现在用线程池并发(默认 6 路,ANIMA_SELECT_DOWNLOAD_WORKERS 可调,设 1 退回串行对照排查),
输出顺序与串行版逐项一致(pool.map 保序,prompt 与图片不会错配)。
实测 6 张:0.60s → 0.24s(2.53×)(D站 预览图;P站 每张固定开销更大,收益更明显)。ANIMA_IMAGE_CACHE=0 可整体关闭,ANIMA_IMAGE_CACHE_DIR 可换目录。
缓存落在 data/image_cache/(纯运行时数据,不入库、不随包发布)。_danbooru_session.headers +
_gallery_header_lock」传 P站 Referer 等必需请求头,那把锁会让所有第三方取图排成一条队 ——
并发下载对 P站/C站 会完全无效。现在请求头走 per-request extra_headers
(_danbooru_get_image 新增该参数),全局头锁已删除。session.proxies.clear()/update() 改为整体原子赋值 ——
两步之间并发的取图线程会读到空代理(= 直连),与 _apply_danbooru_proxy() 的既有约定对齐。ANIMA_SELECT_DOWNLOAD_WORKERS=1 退回串行;怀疑缓存干扰取图时 ANIMA_IMAGE_CACHE=0。.py 改动需重启 ComfyUI(本机已装 tk-hotreload 热重载器,保存即生效)。anima_gallery_safebooru.py、
anima_gallery_moebooru.py)。三者都不需要 API key,走公开 API:Safebooru 属 gelbooru-dapi 系;
yande.re 与 Konachan.net 由同一套 moebooru 骨架服务(两家 post.json 键名实测同构)。
加上原有的 D站 / C站 / P站,一个画廊节点共 6 个图源。anima_animadex.json.gz,2.77 MB,100% 带触发词与预览图),支持中英双语联想、
收藏 / 最近两个页签、作品可搜索筛选(3,702 个作品)、键盘导航;点选后把基础提示词写进
节点 Prompt 输出(selection_data.role_prompt),配合 prompt_settings 关掉原有角色类别即可换人物。
后端 anima_animadex.py + 前端 web/js/anima_animadex_panel.js,路由
/anima/animadex/{search,suggest,facets,status,refresh,image}。
选词拼接不走 LLM —— 离线、确定、毫秒级。anima_tag_index.py(20.6 万标签前缀索引 + 中文 2-gram 倒排),
联想从 835 ms 降到 1~2 ms(hatsune_miku 1046 ms → 1~2 ms;蓝档 32 ms → 2 ms)。
配套修掉每次请求全量重探 6 个代理端口的问题(30 s 缓存 + 首个活端口即返回,实测省下 512 ms/请求)。PortalDropdown)。
工具条高度 7 行 → 5 行(250 px → 188 px)。limit 形同虚设:series_facets() 硬编码 min(200, …) 且路由默认 200、
前端不传 limit,3,702 个作品只放出 200 个(94% 选不到)。已改为全量返回(防呆上限 5000),
端到端复验 sum(count) = 36,488。cursor + 1(-1 起按 ↓ 不移动),已修。konachan.com / anime-pictures.net / waifu.im 在本机出口被 Cloudflare 挑战页拦下(Just a moment...),
属出口 IP 信誉问题而非站点不可用,故本轮接的是全年龄镜像 konachan.net;换网络环境可再评估。web/js、web/css 改动 Ctrl+F5 即可;.py 改动需重启 ComfyUI(或使用本机热重载器)。TK 光影提示词 节点(AnimaTKLightingPrompt)整体移除:删除 anima_lighting_prompt.py
与其 __init__.py 注册(导入 + 两张映射表合并项),并同步清掉 README / docs/FEATURES.md
的节点说明与 tests/test_lighting_prompt.py。
光影预设改由 Prompt 库 / Prompt Cards 承载,插件不再内置光影词表。
AnimaTKLightingPrompt 节点在升级后会成为
缺失节点(红框),其 lighting_prompt 连线一并失效。请把该路输入改为 Prompt 库 /
Prompt Cards 输出的提示词串,再删除缺失节点。web/js)与该节点无关,无需改动;面板开发目录 civitai 侧同步删除了
该节点文件、测试与 scripts/release.mjs 的发布文件清单条目。本版四项功能来自一份外部贡献补丁(
adg-gallery-fixes)。合并前做了两路独立审查, 审查抓到的问题已在合并时一并修掉(见下方「修复」);贡献方原说明见包内《修复说明.md》。
D站 差分组(父子级 / 差分作品):存在差分关系的作品在卡片右上角显示角标
(绿「父帖」= 该作品有子级差分、橙「子帖」= 该作品有父级),操作条出现「差分」按钮。
点击后按 D站 官方语义用 parent:<根帖id> 重搜 —— 有父级时以父帖为根,一次取得
「父帖 + 全部差分」;搜索框旁出现「← 返回 <原搜索词>」还原进入前的**搜索词与页码**。
该跳转**不写搜索历史**(`parent:
依据:D站 posts.json 原生带 parent_id / has_active_children,而 parent:<id> 的语义是
parent_id = id OR id = id,一次请求即可拿到整组,无需新增后端路由。
P站 多页作品折叠 + 全页展开:一个作品(漫画 / 图集)在搜索结果里只出一张卡(第一页),
右上角角标显示总页数(如 12页)。此前 2.19 为修「P站 只显示第一页」把「一个作品 × N 页」
展开成 N 条 item,前端未消费页数字段,N 条全铺进瀑布流:一页变成上百张卡、视口外的卡片
永远选不中,而翻页又按上游批次推进、进一步错位。
现在点操作条「全部页」可展开该作品全部页(角标变 3/12,等价于 pixiv 网页点进 artworks/<id>),
搜索框旁「← 返回 搜索结果」瞬时返回 —— 详情态只是展示层覆盖,不动搜索结果、光标栈与页码。
详情态下不触发自动补图(否则补图会重搜、把人静默踢出详情)。
P站 悬停浮窗(含标签官方翻译):P站 卡片原本没有悬停浮窗,现在复用 D站 那套展示 pixiv 标签,
同样支持点标签直接搜索;小字为 pixiv 官方翻译(后端 tag_details[].translated_name,
Accept-Language 出厂即中文优先 —— 无需抓网页数据),本地中文词典命中时优先用中文。
pixiv 标签仍然不参与 Prompt / metadata 输出(上游既有设计:模型读不懂 pixiv 标签词表)。
悬停浮窗改为「停留才弹 + 锚点冻结」:此前浮层在进入卡片时立即弹出、且位置跟随光标 —— 光标一动浮层就跟着挪,2.19 新加的「点标签即搜索」实际点不到。现在: 悬停 350ms 才弹出(快速划过一串卡片不再弹一堆浮层);鼠标移动只记录停留点、不再驱动定位, 浮层位置在弹出时定格;鼠标移出卡片仍有短延迟窗口,让光标能移进浮层点击标签。 浮层内容与样式未改,只改出现与消失机制。C站 依旧不可交互(其”标签”是提示词分句、且上游忽略关键词参数)。
parent:<id> 永久写进搜索框(合并审查抓到的 S1,唯一会破坏既有行为的项):
差分组期间搜索框里是临时的 parent:<id>,而换源时「先离开差分组、再保存本栏目的搜索词」的顺序
会让这个临时词被记进该栏目的槽位,切回那个栏目时搜索框永久变成 parent:<id>,
且「← 返回」已不在、用户无法还原。改为先取出 diffContext.returnQuery 再离开差分组。submitSearch(不写搜索历史,正确),
但没有补上 submitSearch 额外做的「收起联想 / 历史浮层」与「滚回顶部」,进入与返回都停在半空。
现在进入时补 hideSuggestions(),返回时补 hideSuggestions() + 滚回顶部。renderPosts 会收掉浮层(补图 / 筛选 / 分类都会重建卡片),
而光标仍停在同一张卡上时 mouseenter 不会再触发,要”移出再移入”才会重新弹。
现在 mousemove 里补排一次显示。has_active_children(不是 has_children)——
子帖全被删除时前者为 false,而那时 parent:<id> 只会回自己一张,画「父帖」角标反而误导。
这与 D站 网页的绿框口径略有差异,是有意收紧。renderPosts 现在用 const posts = this.displayPosts()
取渲染源,空结果早退跟着改成局部变量)—— 只改锚点、不动断言语义。tests/test_gallery_diff_and_pixiv_pages.py(12 项契约,含上面 S1 / S2 / N1 的回归锁)。run_tests 6/6、node --check 通过。画廊搜索历史:搜索框聚焦时(内容为空)就在联想浮层的位置显示「最近搜索」,点一下即重新搜; 每条可单独删除(hover 显示 ✕),顶部「清空」清掉当前栏目的全部记录。
需求只说了”记录最近的几次搜索、可以简单地点击调用”,下面这些细节是按使用场景补足的:
age: / ratio: 一起复活。submitSearch()。
翻页、补图、换源重搜、筛选与设置变更重搜、自动纠错重搜、错误重试、初次加载一律不记
(search() 有 30 个调用点,其中 ≥14 个是状态驱动,不是用户的一次检索)。_ / + / 空格视为同一标签(D站 里 long_hair 与 long hair 是同一条)。saveSettings() 里带 setDirtyCanvas,写属性会让每搜一次就把工作流标脏。新增回归锁 tests/test_gallery_search_history.py:锁住「记录点唯一且在 submitSearch 内(search() 本体不得记录)」、
「历史绝不进工作流属性」、「分页 / 补图仍走 this.search,因而不会进历史」、「UI 复用同一个浮层容器」、
「历史项必须拦 pointerdown / mousedown(防 ComfyUI 激活面罩吃掉点击)」。
D站画廊的 Prompt 悬停浮层变成可交互:鼠标能移进去、点标签即搜索。此前有四个障碍叠在一起,
使鼠标物理上够不着浮层:pointer-events: none(浮层不接收事件)、卡片 mouseleave 立即
remove()(无任何缓冲)、浮层挂在 document.body 下(不在卡片子树里),以及浮层是个”移动靶”
—— 锚点每帧跟着光标走,浮层恒定贴在光标右下 14px,鼠标朝它移动它就同步移开(gap 归零也进不去)。
现在(仅 D站):
mouseleave 改为延迟 180ms 隐藏,浮层的 mouseenter 取消它 —— 这条窗口把”卡片→浮层”
的那一瞬接了起来;mousemove 只在卡片内触发,所以离开卡片后锚点自动冻结,浮层停在原地等鼠标。.is-danbooru(pointer-events: auto),于是能停留、滚动(长标签列表终于翻得动)。严格只作用于 D站:C站/P站 的浮层行为不变 —— 判据取自卡片自己的 dataset.source
(D站 是空串),C站 浮层没有 .is-danbooru、仍是 pointer-events: none,鼠标依然移不进去、
标签也不可点(C站 的 prompt 是自然语言分句、P站 不提供 prompt,按标签检索无从谈起)。
独立对抗性审计逐条核对过 6 条隔离断言(CSS 类唯一写入点、dataset.source 无漏写路径、
后端硬编码图源 id、mouseleave 假分支净等价、elementsFromPoint 不含 pointer-events: none 元素、
测试契约未触犯),并据此修掉了下面两条外溢。
renderPosts() 从不隐藏浮层,若用键盘回车搜索而鼠标正停在浮层上
(既无 mouseleave、也没有待触发的定时器),旧浮层会滞留在屏幕上。现在 renderPosts() 头部会收掉
可交互浮层(只收 D站 的,C站 浮层的生命周期维持原样)—— 条件是”卡片已不在文档里”或”当前已不是
D站 视图”,后者兜住换源之外的残留路径(残留浮层带着 pointer-events: auto,会浮在别的栏目上且标签可点)。.adg-prompt-tooltip 加进 PORTAL_INTERACTION_SELECTOR,显式声明
“浮层的点击归浮层”,不再依赖「浮层恰好不在任何 data-node-id 内」这个隐式巧合去阻止节点侧的
点击补发(recoverPointer)。pointer-events: none 的元素不进 elementsFromPoint 命中栈,
所以这条对 C站 的浮层天然不生效。工具箱 · Outputs 栏目「导出元数据开关」(去元数据 + 自定义署名覆盖)。用户在 Outputs 里
下载 / 打包下载 / 复制到剪贴板 / 大图预览 / 编辑器保存副本时,图片副本会自动去掉 ComfyUI 写进
PNG 的 prompt 与 workflow(提示词与工作流不再随图外流),并写入自定义署名
(预置 Author / Copyright / Software / Comment,可增删自定义键值对)。
IHDR / IDAT 等图像数据原样搬运,
不重编码、不改一个像素(不引入 canvas 重绘或图片库重存,ICC / 色深 / 透明通道全保留)。
实测 42 MB 图处理一次 30–34 ms。Author;处理幂等。tEXt(最大兼容性),含中文 / emoji / 代理对的署名自动改用
iTXt 的 UTF-8 形式(无损,PIL 可完整读回)。prompt / workflow(另含 A1111 的 parameters,用于清理从别处拿来的图),
其余元数据(eXIf / tIME / pHYs / 其它 tEXt)以及 IEND 之后的尾随字节一律保留。scripts/verify-image-metadata.mjs(25 项自检:像素零改动 / 幂等 / 覆盖语义 / 尾随字节保留 / 畸形图不动)。prompt / workflow,方便拖回 ComfyUI 恢复工作流)。workflow 块后,图片拖回 ComfyUI 无法恢复工作流 —— 这是本功能的预期效果,UI 上已写明。画廊本地分类库(跨节点共享 + 按图源隔离)。分类以前存在每个画廊节点自己的 settings 里
(会随工作流写进 node.properties),所以同一工作流里两个画廊各有一份、互不可见
(用户实报”多个画廊的分类居然不是共享的,这是巨大毛病”)。现在 data/gallery_categories.json
是唯一真源:分类定义 + 每条归类(含图片快照)都落库,所有画廊节点、所有工作流共享。
同时按 图源分区(D站 / P站 / C站 各一套分类)—— 用户第二轮实报”D站和P站的分类还不是独立的”,
现在 P站 建的分类不会出现在 D站 的下拉里、计数也各算各的;同一图源内仍跨节点共享。
分类浏览不再回查图源:每条归类同时存一份协议层 ITEM_KEYS 快照(图片 URL / prompt / 尺寸 / 图源…),
分类浏览直接读本地快照。原实现是「拿到 id → 按 id: 元标签回查 D站 帖子」,而 id: 只有 D站有,
P站/C站 的分类浏览永远是空的(用户实报”P站画廊的分类是个摆设”)。现在三个图源通用,
且原图失效时也只是少一张缩略图,不会静默丢条目。
卡片「分类」按钮 + 点选式归类:单张归类、Ctrl/Shift 多选后「归类选中 N 张」、标签一键建分类 (点 D站 标签即建分类并归类,零打字)、分类徽章、分类下拉里 ✎ 重命名 / ✕ 删除。
P站 多页作品展开:一个作品按 meta.page_count 每页产出一条(此前只显示第一页)。
各页 URL 只差 _pN 一段,字符串替换即可,不必为每页各发一次 /v1/illust/detail;
分页语义按作品算(先取 raw_items[:size] 再展开),单页作品 id 不变、多页 id 带页码(123456_p1)。
归类”看着成功、其实没落库”(用户实报”分类创建了,却切换不进那个分类”)。两个叠加的根因:
① postKeyOf() 用 post.source 当图源前缀,而 D站 原生 post 的 source 是「作品来源 URL」
(twitter/pixiv 链接),键变成 https://twitter.com/…:4583512,后端按前缀分区时落进一个
不存在的源,归类以 400「目标分类不存在」失败;② 前端 assign() 又用成功文案盖掉错误提示。
现改用 postSourceId(),失败时如实报「归类未完成:N/M 张没写进分类库」;
后端同时收口:非法前缀(含 ://、id 含 /、"pixiv:" 空 id)一律报错,绝不隐式造出垃圾分区。
归类没带图片快照,分类里点进去空白:卡片按钮传的是 postKey 字符串,而
snapshot: isKey ? undefined : … 把快照整条丢掉,后端只能存 {}。现在按 key 从 post 索引取快照,
取不到会如实提示。旧记录用 .scratch/backfill_gallery_snapshots.py 按 id 回查图源补上。
P站/C站 没有”进入分类”的按钮:categoryDropdown.element.hidden = !isDanbooru 是旧语义残留
(分类浏览早已改成读本地快照),现在三个图源都显示。
.corrupt-* 再返回空库,随后一次写操作就把空库写回主路径,用户”分类全没了”);
PermissionError 一律抛错不改名。msvcrt / POSIX fcntl):多开一个 ComfyUI 或运行中跑脚本时不再丢更新。migrate() 不再产生分区内重复 id、不再绕过数量上限、已有归属时可补填空快照。NaN/Infinity 不再落盘(会让浏览器 JSON.parse 抛错、整个图源的分类读不出来)。更新时”其它画廊节点”的旧分类也会被一并迁移:分类库后端化时只迁移了当前节点的 settings,
而 localStorage 里每个节点各存一份,别的节点的归类从来没被迁移过(用户实报”我的分类怎么就三个了,
原本有七八张”)。新增 collectStoredCategoryBackups():扫 localStorage 里所有画廊节点与旧版全局键,
一起并进共享库(当前节点那份优先、其余只补缺,成功后打一次性标记)。
分类的重命名 / 删除只改前端内存(不落后端),下次加载被后端那份覆盖回来(”改了又变回去”)。 现在统一走后端,删分类会把其中的图片退回「未分类」(不删条目)。
document.body 追加新浮层,旧浮层永久留在屏幕上
(已单例化);② 飘在节点外 —— 只监听 resize/scroll,而画布平移/缩放两个都不触发
(已加画布 pointerdown/wheel 即收起);③ 点候选后又冒 —— 候选走 setQuery() 会再排一次联想
(已在 search() 开头统一 hideSuggestions())。Tag Getter「过滤诊断」底栏不再空白(2026-09-20 用户实报”过滤诊断没有任何内容输出”)。
根因:ComfyUI 的 ui 通道约定每个值必须是 list(execution.py 用
ui = {k: [y for x in uis for y in x[k]] for k in uis[0].keys()} 展平),而本节点回传的是 dict,
for y in dict 只迭代出 keys,前端拿到 ['auto_classify','kept',…]、所有字段 undefined,
底栏退化成误导性的「本次执行没有被过滤或未归类的词。」(真机 executed 事件实测
tkType:"array")。现改为回传 [报告](符合约定),前端读取同时兼容历史 dict 形态。
顺带修掉双输入模式(接了 TAG_BUNDLE)漏 ui 通道——那条路径原先只 return (tag_text,),
诊断栏永远收不到数据。
手动改动的开关/权重不再被「场景预设」静默覆盖(2026-09-20 用户实报”明明关闭了背景词却输出
simple background“)。根因:get_tags 执行期调用 _apply_preset(preset, category_flags),
而自定义预设存的是完整开关快照、_apply_custom_preset 对每个分类无条件覆盖 ——
于是提交值确实是 false(GET /history/<id> 的 prompt[2] 可证)却被盖回 true,且面板看不出来。
现改为 「显式传参优先、预设只补缺省键」:GUI 与 API 显式给出的开关/权重一律生效;
只传 preset 名、不传开关的调用方仍拿到整套快照(「选预设 = 整套套用」能力不变)。
内置规则型预设(only/off)语义不变 —— 它本来就是”明确要求只留/关掉这些”。
前端配套:手动动任一开关或权重即把预设名切回「自定义(不用预设)」;载入工作流时对账一次
(开关值与预设快照不一致就摘掉名字),保证「面板显示 == 运行期生效」。
排查陷阱(写给下一位):发布仓库与运行目录的 data/ 不是同一份 ——
发布仓库没有 data/tag_presets.json,离线复现时 _apply_preset 是 noop、结果”正常”,
而真机有预设才被覆盖。复现这类问题必须显式用运行目录的代码与 PLUGIN_DIR。
LORA_WEIGHT_MIN / LORA_WEIGHT_MAX 常量,数字框同步加宽以完整显示 -10.00。
后端 anima_batch_lora.py 的 _parse_lora_syntax 本就用 float() 解析、无范围限制,
本次只放开前端约束(已有回归测试锁定该契约)。loadFullOutputMeta():IDB → /anima/gallery/meta 按需补全 → 落 IDB,二次进入零请求。lorasExtracted: true 在写回时被打回 false,
导致可见区观察器每帧重新入队、反复读空的 IDB(实测一次会话 2.3 万条控制台日志)。现已修正判定。max(candidates, key=len) 只取最长的一段,其余整段丢弃。
现在改为拼接全部候选 + 标签级保序去重;PARSER_VERSION 升到 2,索引换代自动全量重解析。large_file_url 是 sample 档(最长边恒为 850),
下载取值顺序却把它排在原图 file_url 前面。现在原图优先,并在 file_url 缺失时
把 sample 直链改写成 original 直链;下载文件名也从实际 URL 推断扩展名(原图可能是 png)。settings.lastQuery(只在点搜索时才更新),
改了词但没点搜索就直接保存,存进去的是上一次搜索的词,备注也随之翻成上一个词的翻译。
现在以搜索框实时输入为准,并在提示里回显实际保存的搜索词。navigator.clipboard.writeText() 在页面失焦/权限被拒时
既不 resolve 也不 reject,后面那句 showToast 永远不执行。现在加 1.2s 超时 + 回退并给出明确提示。will-change: transform(每节点一个合成层,
且该条单独收益为 0);DOM 面板尺寸同步改为幂等写样式、不再在 resize 回调里同步读写(避免强制重排)。docs/FEATURES.md。TK D站画廊 节点新增图源下拉,同一个节点切换三个图源;
后端新增协议层 anima_gallery_sources.py(统一 item schema、图源注册表、适配器容错加载)
与 anima_gallery_civitai.py / anima_gallery_pixiv.py 两个适配器。withMeta=true 以取回完整 prompt 与采样参数。Referer 以通过 i.pximg.net 防盗链。opacity:0)时未禁用命中,
导致卡片顶部一整条隐形按钮吃点击(表现为”按钮太大、老误触”,点图片上半部却触发下载/入库);
现改为隐藏即 pointer-events:none,并把操作条从图片上移到卡片底部 caption 行(与图片重叠面积为 0)。Tab 接受当前候选、Enter 还给换行(仅在按过 ↑/↓ 之后才确认所选)、
Shift+Enter 永远换行、输入法组字期间不再拦截按键(此前中文上屏会被误判成选词);
候选高亮与鼠标悬停同步。此前 Enter 被无条件占用,候选列表一出现就无法在多行提示词里换行。aiohttp.web.json_response 被换成假实现后从不还原 / requests 光秃桩 / _FakeSession 缺属性)
—— 症状统一为”单跑绿、全量跑红“。GET /api/v1/me);NSFW 档位匿名亦可读取。split_prompt 契约是「空行之前切标签、
空行之后整段视为自然语言」,而自然语言按设计不参与 dedupe —— 用户把两批标签用空行粘在一起时,
第二段整段被当自然语言,跨段重复词(1girl / blue sky / smile / long hair …)全部留着。
现在格式化节点会先判断「空行后的段是不是其实又一批标签」(无句末标点 + 逗号片段 ≥3 + 无长句片段),
是就并进标签一起参与去重与重排;真句子照旧保留(判据刻意保守,宁可把标签当自然语言,也不把句子拆成标签)。
只改格式化节点,未动共享契约。tag_blacklist 命中 / regex_blacklist 命中 / 未归类,分组展示)。
后端 get_tags 经 ComfyUI 的 ui.tk_filter_report 通道回传(每栏限 40 词,不膨胀执行历史)。
点类别名可直接开/关该类并就地重算,不必重跑工作流;若「旧 12 类全关」(= 不启用自动分类、整段原样输出)会显式警告。applyPreset() 原先只查前端硬编码的内置表,自定义预设拿到空 spec →
20 个开关一个都不动(后端 _apply_preset 其实一直是对的)。现在按快照还原开关与权重,
并缓存 GET /anima/tag_presets 的 presets 字段(保存/删除后即时更新)。recoverPointer() 的”补发点击”判据用的是”坐标栈里第一个带 data-node-id 的元素”,
点 ComfyUI 自己的按钮(不属于任何节点)时会一路命中下面的画廊节点 → 误判”同一个节点”而放行 →
穿透到卡片、参考图被换成没想选的那张。改为认事件真正的目标归属(代价:极端情况可能要点两次,但不会选错图)。PRESETS 只剩「自定义(不用预设)」。旧工作流里存着的已删预设名
因为 preset 是 STRING 而非 COMBO,安全降级为”不用预设”,不报 Value not in list。data/tag_taxonomy.tsv.gz,69.3 万标签 /
20 个分类):不再依赖第三方 Tag Sorter 插件,未归类词占比从 98.6% 降到 11.44%;
新增 8 个分类(角色身份 / 作品版权 / 发色发型 / 亚人特征 / 审查遮挡 / 文字水印 / 质量元 / 物件道具),
原 12 类的名字与顺序一个未动,旧工作流可直接打开。AnimaTKLatentSwitch):六路 latent 选一路输出并联动 denoise,
或以一路为背景叠加其余路(羽化 / 居中 / 偏移),模式在节点内切换;
按最后两维处理空间维度,兼容 Anima 的 5D latent。data/tag_presets.json,跨工作流共用)。全开 / 全关 / 反选 / 权重归 1 批量操作;排除框一键清空、权重双击归 1、键盘焦点可见。normalise / tag_lookup_keys /
正则 / 黑名单)加缓存、索引取用改无锁快路径 —— 120 标签的单次查询 1.19 ms → 0.37 ms,
开主题剔除时查表次数从 244 降到 122。POST /anima/cards/zh_lookup
(13.2 万条「标签 → 中文」别名表 + 24 万条词典兜底,均规范化匹配),词典没有才机翻;
批量重译会先整批查词典再决定要不要机翻,另提供「只用词典」档。exclude_groups / exclude_groups_custom 两个控件保留占位
(删控件会让旧工作流的 widgets_values 错位),但前端不再渲染、后端不再参与判定。顺带修了测试基建:test_danbooru_meta 会顶掉真 torch,影响同 session 需要真张量的测试。
probeGalleryIndex() 首次探测成功后永久短路 —— outputThumbnail.ts 里
if (_galleryState !== 'unknown') return _galleryState === 'ready' 让后续所有调用
直接 return,于是 _galleryEntries 永远停在首屏那一版。
refreshOutputsFromGallery() 那句注释写着”索引已重建完则重新载入 entries”,
但实现根本没重新载入。现在加了 force 参数才会真的重拉 manifest。probeOutputsGrew() 只看后端 changed
(磁盘文件数 > 索引里的 total)。而后端重建索引是后台线程:探测到 changed 那一刻
索引往往还没建完,此时拉的仍是旧索引;等它建完后 count 已追平、changed 又变回
false —— 前端据此就再也不来拉了,新图永远不出现。
现在同时比对后端返回的 builtAt(索引构建时刻):只要索引换代就重拉,与 changed 无关;
building 期间跳过,等下一轮。首屏已载入的 builtAt 由 service 记着,不会为此白拉一次 manifest。/anima/gallery/fresh 的判据漏了 latest —— changed = count > known 只判”变多”,
而已经算好的 latest(最新 mtime)根本没用。索引 total 偏大(含已删文件等)时,
新增的图也算不出”变多”。补上 stale = latest > builtAt + 1,并把 builtAt 一并返回给前端。主题切换按钮在浅色主题下几乎看不见(用户截图反馈)。
三个点里只有 [data-theme="mono"] / [data-theme="mono-light"] 定义了背景色,
drinkit 那个点没有背景 → 在浅色主题下只剩 1px 的 --border 淡边,整个控件等于消失。
现在每个点填上它所代表的主题色(drinkit 用 --color-primary),统一加描边;
选中态改成”底色 + 主题色”双层环,比单纯描边更容易看出当前是哪个主题。写在本文件最后
import 的 design-system.css,优先级足以压过 global.css / polish.css。
.outputs-stats 从网格下方的独立卡片移进顶部工具栏同一行,
CSS 从”带背景/边框/padding 的卡片”改为行内紧凑文本(margin-left:auto 推到最右)。
顺带说明:张数在工具栏的「全部图片 (N)」里本来就有,这条属于冗余信息,现在不再占一整行。补回「Outputs 生成完后台更新」的前端部分 —— 发布版一直缺这个功能。
该功能的后端路由 /anima/gallery/fresh 在 2.11.0 已经发了(anima_batch_lora.py 里确实有),
但前端调用只写在 dev 目录 civitai/src/sections/Outputs.ts,从未镜像到 panel/src。
后果:app/、registry 包、ComfyUI-Manager 安装的用户全都拿不到 ——
后端有路由、前端从不调用,功能静默失效;而 AGENTS.md / HANDOFF 里写着 2.11.0 已包含它,
文档与代码不一致。
判据(可复现):在构建产物里 grep 字符串字面量 gallery/fresh / execution_success
—— minify 不会改字面量,所以产物里查得到才算真发布。修复前:dev src 有、panel/src 没有、
app/assets 没有。
双向漂移合并:LoraExplorer.ts 的「版本下拉脱离裁切」修复(applyDropdownClip /
releaseDropdownClip)只存在于 panel 侧 —— 2026-09-12 是直接在发布仓库改的,dev 目录没有。
已回写 dev,否则以后从 dev 构建会把这个修复静默回退。
合并方式:逐文件用 difflib 看「少数派」差异块,确认哪边是超集再整份覆盖
(Outputs.ts 无 panel 独有改动 → dev→panel;LoraExplorer.ts 的 dev 侧只是被重构掉的旧写法
→ panel→dev)。合并后 sync_panel_src.py --dry-run 全部 same。
sync_panel_src.py 全量镜像 ——
那会把 panel 侧独有(在发布仓库直接做的)改动回退掉,而且没有任何报错。app/ 是坏的。2.12.5 发布时我为了本机验证重建了 app/,
但 comfy node pack 只打包 git-tracked 文件 —— 新构建出来的 hash 文件当时还没被跟踪,
于是被跳过,而 app/index.html 已经引用它们。打包日志已经点名:
File not found. Not including in zip: app/assets/index-BeUX-0M9.css。
改法:不手工提交 app/(按 AGENTS.md 由 CI 的 build-app.yml 拥有),
等 bot 的重建提交 chore: rebuild panel app 落地后再发版;本版 app/ 即 bot 的产物,
实测 index.html 引用的 index-Chynkz48.css 含 #f2f3f5,且 app/ 与 git 完全一致(pack 不再告警)。
2.12.5 的 registry 版本作废(仍是 Pending,未被安装)。教训(已写进
AGENTS.md坑 9 的语境):改了panel/之后不要在本机 rebuildapp/再发版 ——app/是 CI 的产物,本地重建会让「git 跟踪的清单」和「磁盘内容」错位,打包静默漏文件。
drinkit)下 toast「黑字黑底」:global.css 的 .toast 背景是写死的深色
rgba(10,10,12,.92),但文字用的是 color: var(--text)。深色主题(mono)下没问题,
可 drinkit 是 color-scheme: light(--text 是深色)→ 于是出现黑字黑底。
用户截图里的「请先选择目录」就是这么看不见的。
而 drinkit 还是 main.ts 里的默认主题(localStorage.getItem('anima_theme') || 'drinkit'),
只有 mono-light 有 toast 覆盖 —— 默认主题反而漏了。
改法:.toast 文字写死浅色 #f2f3f5(背景既然是固定深色,文字就该固定浅色),
这样一次性覆盖 drinkit 与未来任何浅色主题;mono-light 的浅底深字覆盖保持不变。
顺带用脚本扫了全量 CSS 的「写死深色背景 + var(--text)」组合,只有 .toast 一处,不是系统性问题。Tk Toolkit → TK Toolkit(全大写)。理由:面板自己的按钮本来就叫
TK Toolkit / 本地工具箱(panel/src 里既有),15 个节点显示名也一直是 TK xxx;
全大写才和产品内既有叫法一致。节点显示名完全没动(保持 TK xxx)。时运Tk → 时运tk(与 B 站账号一致,tk 小写)。说明:2.12.3 那条 CHANGELOG 里写的
Tk Toolkit/时运Tk是当时的事实,作为历史记录保留, 不回改。另:本次改的是panel/src,app/由 CI 的build-app.yml重建(不手工提交)。
anima toolkit 从 1 条(我们)变成 0 条 —— 我们本来是它唯一的匹配。而旧版 Release
(v2.10.0–v2.12.2)、旧 README、旧教程、以及 AI 的训练语料里都写着 “Anima Toolkit”,
这条查询路径不能断。
改法:description 写成 “Tk Toolkit (formerly Anima Toolkit) — …”,README 英文摘要与
llms.txt 各加一句 “formerly Anima Toolkit(2026-09 改名)”。
这样新旧两个名字都能召回,AI 也能把旧名映射到新名。项目改名为 Tk Toolkit(作者「时运Tk」的品牌)。原显示名 “Anima Toolkit” 与训练工具链
AnimaLoraToolkit(66 星) 撞脸 —— 搜 “anima toolkit comfyui” 时对方排第一,AI 容易把我们归错类;
另有一个同名 fork bfftp0502/comfyui-anima-toolkit。
改名范围刻意只动”对外身份”层(零风险,老用户完全不受影响):
| 改了 | 没改(改了会出事的) |
|---|---|
Registry DisplayName → Tk Toolkit |
Registry 节点 id 仍是 anima-toolkit(换 id = 建新节点、重新排队审核,还会在 registry 留一个重复节点) |
| README 标题 / 英文摘要 / 安装块 / 图标 alt | GitHub 仓库地址不变(老用户更新链硬编码了旧仓库名;且旧名释放后有被抢注的供应链风险) |
pyproject description + authors |
NODE_CLASS_MAPPINGS 类名(已保存的工作流 JSON 存的就是这些字符串) |
llms.txt / AGENTS.md / CLAUDE.md / 两个模块头注释 |
anima_ 文件与模块前缀(更新链白名单就是 path.startswith("anima_"),改了等于重踩漏发 bug) |
节点显示名保持 TK xxx(38 处代码 + 34 处测试断言,纯 churn 且无检索收益) |
召回不掉:Anima 关键词保留在 description 里 —— 实测 registry 搜索会索引 description
(搜 danbooru 能搜到我们,而 “danbooru” 并不在节点名里),所以从 “Anima Toolkit” 改成 “Tk Toolkit”
不会丢掉 anima 这个查询词。
作者署名:[project].authors = [{ name = "时运Tk" }]。刻意没写 email —— 一提交就进公开仓库
历史、无法撤回;要公开再补 email = "..."(PEP 621 允许只填 name)。
screenshots/icon.png(400×400,由 tools/make_icon.py 生成,
取自面板自身配色),并在 pyproject.toml 填上 Icon。此前 registry 上的 icon 是空的 ——
registry / ComfyUI-Manager 列表里没有缩略图,直接影响点击与发现率。llms.txt(仓库根):面向 AI/LLM 的机器可读摘要 —— 一句话定位、安装命令、全部节点清单、
关键词、以及”别认错”说明。新兴的 LLM 友好约定,成本极低。## Installation / 安装(Manager 搜索名 + git clone
命令 + registry 链接 + 依赖指引)。此前前 4000 字符里 install 出现 0 次 ——
需要”替你安装”的 agent 找不到可执行指令。关键词补上
comfyui-manager / tag-autocomplete / chinese-tag-autocomplete / workflow-automation。AnimaLoraToolkit(66 星) / AnimaLoraAtelier 是训练工具链,
搜 “anima toolkit comfyui” 时它排第一。README 与 llms.txt 都写明本项目是推理侧
工具包(加载/管理/检索 LoRA,不训练),避免 AI 把我们归错类。遗留:registry 上的
category/tags仍是空的 —— comfy-cli 的[tool.comfy]只认PublisherId/DisplayName/Icon/includes(实测其config_parser.py), 这两个字段只能在 registry 网页端补,不是代码问题。三个版本的审核状态仍是Pending(latest_version因此为空),审核通过前 Manager 的注册表安装路径不会列出来。
services/ 与随包词典。发布白名单曾把 data/ 与 services/ 整个排除,
后果有两个:
① 新词典永远下发不到 → 中文联想在老用户机器上表现为”代码在、索引不在”,不报错但没用;
② services/ 不下发 → __init__.py 拆分后 from .services.github_update import … 是硬依赖,
点更新会拿到新 __init__.py 却拿不到 services/ → ImportError,插件整个加载不了。
现在 services/ 全量下发;data/ 改为逐文件白名单(只放行随包词典,
prompt_library.json / batches/ / 账号 / 缓存等用户状态永不覆盖);
别名索引改放插件根目录 anima_alias_index.json,这样连旧版更新链都能把它下发下去。望/橘望 → nozomi (blue archive)、妃咲/龙华妃咲 → kisaki (blue archive)、
日奈 → hina (blue archive)、星野 → hoshino (blue archive)。
数据来自两层可验证来源,不含任何 LLM 编造:
① 社区词典与官方译名(data/danbooru_tags_zh.json、原 CSV 的「关键词」字段);
② 从 Civitai LoRA 元数据里挖出的真实配对(中文标题 ↔ trainedWords 里的 danbooru 标签,
共 2638 条,每条都带证据)。
另引入 AnimaDex 角色表(36,480 个角色 / 3,702 部作品),所以输入作品名
(如「碧蓝档案」)也能直接列出该作品角色。data/ 与
services/ 整个排除。后果有两个,第二个更严重:
① 新词典永远下发不到 → 2.12.0 的中文联想在老用户机器上表现为”代码在、索引不在”,不报错但没用;
② services/ 不下发 → __init__.py 拆分后 from .services.github_update import … 是硬依赖,
老用户点更新会拿到新 __init__.py 却拿不到 services/ → ImportError,插件整个加载不了。
现在 services/ 全量下发;data/ 改为逐文件白名单(三个随包词典下发,
prompt_library.json / batches/ / 账号等用户状态永不覆盖);别名索引改放插件根目录的
anima_alias_index.json,这样连旧版更新链都能把它下发下去。telescope:说明字段里的「望远镜」曾让天文器材标签排在角色前面 ——
中文查询不再扫描英文说明,只在别名表完全没有结果时才回退。tests/tools/run_offline_like_ci.py 报告失败时自身崩溃:失败分支里的 ❌ 在 GBK 控制台上
触发 UnicodeEncodeError,把真正的报错盖掉(与 ai_verify.py 同一个坑),已改为纯 ASCII。(x) 会加强 x),
要拿到字面标签 nozomi (blue archive) 必须写 nozomi \(blue archive\)。
与 D 站画廊的「转义括号」同一套语义(反转义后再转义,重复插入安全)。
②区工具栏新增 括号转义 开/关 按钮,可随时切回裸括号;该选项保存在本地 UI 状态里。热门随机(评分 ≥100)/ 优质随机(≥50)/
高收藏随机(收藏 ≥30),均为 order:random 配质量地板,避免裸随机倒进没人贴过的冷门图。
带 force=1 绕过 30 秒缓存(否则”随机”会给出完全相同的一批);换一批会检测是否真的换出新图,
池子见底时明确提示而不是假装换过;内容标签与随机池无交集时自动退化为纯随机并说明。GET /anima/gallery/fresh(只遍历输出目录文件名并 stat,
不解析 PNG、不返回 16.5MB 索引),并监听 ComfyUI 的 executed / execution_success 事件。
不在 outputs 页面时也会在后台把新图准备好,切回来立即可见
(旧实现只在窗口获焦/切页时扫描、隐藏时直接 return —— 正是”不进页面就不更新”的原因)。.github/workflows/ci.yml):Python 编译 → ai_verify → 离线 pytest →
JS 测试 → panel tsc → panel 构建,每个环节独立 step、失败环节一眼可见。
权限只有 contents: read、不做任何提交,与负责提交 app/ 的 build-app.yml 完全分开;
push 到 main 与 PR 都跑,pip/npm 双缓存。tests/ 按「正式回归 / 需要真实环境 / 一次性脚本 / 工具」分层
(unit 23 / js 3 / integration 57 / smoke 4 / repro 12 / tools 5),
清单由 tools/classify_tests.py 生成并由 test_layer_manifest.py 守卫;
新增 python tests/run_tests.py:本地跑的等于 CI 跑的那一套。pyproject.toml(按当前官方规范)与
requirements.txt(必需依赖)/ requirements-optional.txt(playwright、llama-cpp-python)。
刻意不声明 torch / numpy / PIL:由 ComfyUI 自带,重复声明会引发版本冲突。order 曾被错误地算作免费 metatag,
导致「计数标签超限时自动移除排序」的分支与其提示条变成死代码
(回归 test_danbooru_gallery_interactions.py 自 2026-09-07 起一直失败,却被记成”预存在失败、非本轮引入”)。
现已修正为占 1 槽,前后端语义一致。rating:g / -filetype:mp4(历史写入),
会与筛选面板各拼一次 → 白占计数槽,还会让”退化重试”拿到一模一样的查询而形同没重试。
现已让筛选面板成为这些 token 的唯一 owner(与 order: 已有的规矩一致),并加大小写不敏感去重。PROMPT_LIBRARY_BACKUP_PATHS 在导入时从
PROMPT_LIBRARY_PATH 派生并固化成常量,而 save_snapshot 用的是当前值 ——
一旦数据目录被重定向(测试隔离必做),主文件写新位置、备份却写旧位置,
而 load_snapshot 又去新位置找备份。现改为按当前路径现算。web/ 里放过备份文件,会被 ComfyUI
当扩展一起加载、registerExtension 跑两次。备份已移出 web/,并立规矩:
web/ 是会被服务出去的目录,任何 .js 备份都不能放在里面。ai_verify.py 只在有 FAIL 时崩溃:其中用了 ❌ / ⚠️,默认 GBK 控制台下 print 会抛
UnicodeEncodeError —— 恰好在你最需要它报告失败的时候。已替换为 ASCII 标记。assert / sys.exit(),
pytest 要么收集期 INTERNALERROR,要么导入时执行且失败不会被报告(静默假绿)。
已全部改造为可被收集的正式用例(含”安全更新 ZIP”的回归)。
另修正 3 处从来没通过过的断言(引用不存在的变量、断言写死整串 HTML)。__init__.py 拆分第一阶段:2657 → 2448 行,把 GitHub 自动更新链拆到
services/github_update.py(边界最清晰、且有独立回归兜底)。
__init__.py 保留薄适配层与两条路由(所有 /anima/* 的唯一入口要集中),
会话与目录用显式注入避免循环导入;路径穿越校验与逐文件回滚逐行照搬、未做任何简化。VERSION 成为唯一真源:__init__.py 的 __version__ 改为运行时读它;
ai_verify.py 新增版本一致性检查(VERSION / __version__ / README / CHANGELOG / pyproject 五处,任一处漂移即 FAIL)。tools/bump_version.py:发版时一处改、五处同步,避免手改漏项。docs/FEATURES.md 清掉残留的写死版本号(v0.4)。TK 相机控制 节点已退役移除,由 TK 可动素体相机 取代。旧工作流里的该节点会显示为
「缺失节点类型」,请删除后改用素体相机:机位参数(pos_x / pos_y / pos_z / roll / fov)
与输出端口(camera_prompt / camera_meta)语义一一对应,预设与权重算法同为 CameraControlCore,
换节点即可,无需重新调参。web/js/anima_camera_control_widget.js 一并删除(节点已不存在)。anima_camera_control.py 模块本身保留:素体相机通过 CameraControlCore / DEFAULT_CONFIG_JSON /
CUSTOM_PRESET / all_preset_names 复用它,删除该文件会导致素体相机失效。.version-dropdown 是 position:absolute; bottom:100%
(向上弹),而卡片链路上有 3 层 overflow:hidden(.card-body → .card → .vs-card-wrap),
浮层弹出即被裁切。现于展开时临时解除「浮层 → 滚动容器」之间所有祖先的裁剪(含 .card 的
content-visibility:auto)并把卡片抬到 z-index:40,收起时逐级还原;上方空间不足则自动翻转为
向下展开。滚动容器自身保留裁剪,避免整页跟着滚动。TK 节点系列 由十二个改为十一个。trigger_words 输出改为直接输出本节点已激活(权重非 0)LoRA 的触发词,且与「是否加载成功」解耦——文件缺失但被激活的 LoRA 也会带出触发词。禁用项由面板以 <lora:name:0.00> 写入,既不加载也不取词。output_trigger_words,默认开启)。关闭后该输出为空字符串,LoRA 加载不受任何影响。data/lora_trigger_words.json,端点 POST /anima/lora_trigger_words)。执行时按「节点推送的持久表 > 内存 bridge > anima_bridge.json」解析,不再依赖面板是否推送过 bridge,刷新/重启后依然可解析。名称写成全路径 / 去扩展名 / 纯文件名都能命中同一份触发词。_find_lora_path 模糊匹配分支崩溃(重要):该分支调用了从未定义的 base() → NameError。真实文件名带 ` (1) 之类后缀时(例如 ITEFU-KREA-V1 (1).safetensors)必然走到这里,后果是:/anima/lora/info 返回 500(**触发词因此永远提取不到**)、「验证标签」报错,**并且节点执行会直接失败**。已修复并补回归测试 tests/test_batch_lora_trigger_words.py`(18 项,离线可跑)。0 时必须写回 1.0(否则节点按 (tag:0) 执行、该分类 Tag 被静默丢弃),项目自带 UI 测试正是这么判定的。现已把两者合并:空值 / 非数字 / ≤0 一律归一为 1.0 并写回 + 标记工作流已变更,其余值按 0.05 步进夹到 0.05–2。verify_danbooru_tag_getter_ui.py 通过。TKPromptCards 原先一次性渲染整库(实测 984 张卡 ≈ 1 万个 DOM 元素 / 4 千个控件,而卡片区仅 300px 高),现改为首屏 60 张 + 滚动补渲染(保留滚动位置、切分类/搜索时收回首屏)。卡片区 DOM 由 ~10052 降到 ~601。options.hidden(原先整体替换 options 会让前端判定失效),消除 12 个整宽遗留 <canvas> 行:canvas 12 → 1 张、占用 10.4MB → 0.8MB。web/js/anima_canvas_perf.js 节点级渲染裁剪:为每个节点写入精确的 content-visibility + contain-intrinsic-size(视口外节点跳过渲染)并做图层提升。Chrome Tracing 实测每帧 Layerize 6.8ms → 3.8ms(−44%),平移帧时 −12% ~ −48%(取决于离屏节点比例)。localStorage.setItem('tk_canvas_perf','0') 后刷新关闭裁剪。civitai.red/models/... 链接此前报「无法解析」——URL 解析只认 civitai.com。现已统一为共用解析函数,civitai.com / civitai.red 及未来镜像域名均可;「手动匹配」与「添加 LoRA」入口同步修复。报错信息也会显示完整链接便于排查。纯前端改动,刷新浏览器(Ctrl+Shift+R)即可生效。/anima/gallery/manifest 与 /anima/gallery/meta)——扫描、PNG 参数解析、LoRA 提取、宽高读取全部在本地后端完成(实测 3571 张约 13 秒建库,增量更新 0.4 秒),索引含正向 prompt 全文与 LoRA 列表(支持 ComfyUI UI/API 双格式与「文本拼接 / tag 库节点运行时组装」类工作流的正向链路回溯)。前端打开 Outputs 时一次拉取清单,列表、预览图、全部按钮同时出现;完整工作流 JSON 仍按需获取。索引首次构建期间界面照常可用,构建完成后自动切换。后端不可用时自动回退旧管线。/anima/thumb 生成的 512px 高质量 WebP(LANCZOS,落盘长期复用,按内容自动失效)。单张从约 1.4MB 原图解码降为 30KB 级小图,首屏与滚动加载接近瞬时,预览图不再模糊;后端不可用或图片不在 output 目录时自动回退旧管线,升级无感知。需重启 ComfyUI 生效。/anima/thumb(第一步,前端暂未接入):为下一版「秒开 + 高清预览」打底。512/768 两档 WebP 落盘缓存(LANCZOS),缓存键含源文件 mtime/size(图一变自动失效),带浏览器强缓存头;路径做严格目录校验。生成走旁路线程且并发限流,不影响出图。此版本前端仍走旧管线,升级无感知。nsfw=false,选「全部」时省略该参数;而 C 站 API 省略 nsfw 等价于仅返回 SFW,导致「怎么选都是 SFW」。现在始终显式传参(全部 → true,仅 SFW → false)。resolvedQuery 判定,本地过滤只用于输入防抖窗口内的即时反馈);空状态节点改为幂等复用,不再残留压在卡片上方。hasMore 解耦(updatePager()):只要抓取过(page>0)就保留分页区,仅在没有下一页时隐藏「加载更多」。crypto.subtle 时整文件 digest;大文件仍分块 + Worker),并带取消检查;取消扫描时 progressHide() 复位状态并提示「⏹ 扫描已取消」。civitai.com / 镜像站 / 自定义域名)与只读 API Key;模型与作者链接随线路变化。部分网络下官方域名不可达时可切镜像站。Comfyui-Anima_camera_angle 的路径加载,未安装该插件的机器上节点永远停留在“正在加载本地 3D 引擎…”。现在插件自带 web/js/three.module.js,优先从本插件加载,外部插件路径仅作兼容兜底。width/height 两个 INT 输出口,颜色链等下游可直接读取尺寸。TK Danbooru Tag Getter:修复旧工作流恢复后分类权重变成 0 的问题;0 会按中性权重 1.0 处理,前端最小可调值为 0.05,避免输出 (tag:0)。
natural_language 输入升级为统一 Prompt 入口;没有分类包时会按本机 Danbooru 数据库自动归类已知 Tag,未知句子由“保留自然语言”控制;每个分类可独立设置 0.0–2.0 权重,已有 Tag 权重会按分类权重相乘。分类索引优先读取 Packer 的 xlsx(直接解析 XML,避免 openpyxl 启动开销),找不到时回退随插件 CSV;旧双输入工作流继续兼容。本次版本对应最近推送的 LoRA 子目录功能。
f83d00e):TK 批量 LoRA 加载器和 TK Toolkit 本地管理面板都会读取 LoRA 根目录下的子目录,并保留相对路径。ad3b2b8):本地工具箱新增按钮,按一级子目录名称自动创建/复用分类,将对应 LoRA 批量归类;重复点击不会重复添加。relativePath,统一用 / 表示子目录,并继续兼容 Windows 反斜杠路径。TK String Router:新增 6 路字符串单选/多选路由,支持接口名称保存和 ComfyUI 风格紧凑面板。TK Danbooru Tag Getter:兼容 TAG_BUNDLE 多选分类,增加正则排除和精准 Tag 排除。TK Prompt Saver:新增 6 路提示词自动保存,支持对应 image_1 到 image_6 预览图,写入共享 anima-lora Prompt 库。anima base、ill、sdxl 等用户自建目录。all(not p.strip()))、SaveImage 前缀正则(imageSave 类名)、负向注入保持原值本次版本包含大量更新(跨多轮开发)。
modelVersionId 的链接(无则自动取默认版本)showDirectoryPicker 时用文件选择扫描(Firefox/夸克旧版/局域网 IP)web/)