Repository navigation
Releases: TinyNano/TinyChat
Release list
TinyChat v2.1.1 · 修复新增界面的输入控件样式
[2.1.1] - 2026-10-11
修 2.1.0 新增界面里「原生裸奔」的输入控件:记忆面板的新增输入框、设置里的自定义指令文本域、以及动态输入弹窗(UI.prompt / TOTP 验证码)共用的输入框样式。
修复
- 记忆面板新增输入框:此前是没有任何样式的裸
<input>(浏览器原生外观:白底、细灰边、直角),与站内表单格格不入;现改走label.field体系,带标题、圆角、描边与聚焦光环,方块主题下自动获得浅灰底覆盖。 - 自定义指令文本域:同样改为
label.field包裹,不再是一块裸 textarea。 - 动态输入弹窗的输入框没有样式规则:
UI.prompt与 TOTP 验证码弹窗共用的.oc-prompt-input类此前在全部样式表里没有定义,一直按浏览器原生外观渲染(这个问题先于本版本存在,TOTP 弹窗让它显形了);现补上与.field input同一材质的基础样式,并加入方块主题的浅灰底 + 聚焦光环覆盖(白卡片上不能白底白字)。 .field textarea背景一直落成透明:样式里引用的--bg变量从未定义过,所有走.field的多行输入框背景都是透明的;换成既有令牌var(--bg-input),与单行输入框同材质。
测试
tests/new-features-gui.mjs新增两条材质断言(记忆输入框 / 自定义指令 textarea 的 computed style 必须有圆角、描边与非透明底色),防回归。tests/new-features-contracts.js新增两条源码契约(chrome.css 必须带.oc-prompt-input规则、方块主题必须覆盖它;记忆输入框与自定义指令必须走.field体系)。
TinyChat v2.1.0 · 跨对话记忆 + TOTP 两步验证 + 主题升级
[2.1.0] - 2026-10-11
一批以「对话体验 / 账号安全 / 运营可见性」为主线的功能更新,外加方块主题的 Apple 官网化改版。
新增
对话体验
- 跨对话记忆:对话结束后自动提取值得长期记住的用户信息(身份、偏好、进行中的项目),注入之后的每一次对话(服务端在 system 提示词中拼接,对话接口与 API 均生效);设置 → 对话里可一键开关、手动增删、清空全部。提取由前端在对话间隙用辅助模型完成,服务端只做去重 / 上限(默认 50 条)/ 注入,不占写事务。后台可整体关闭。
- 全局自定义指令:设置 → 对话里的长效偏好(如「永远用中文回答」),随设置云同步,注入每次对话;会话内助手提示词仍然优先。
- 回复朗读(TTS):AI 回复操作栏新增喇叭按钮,用浏览器自带语音引擎朗读,再点一次停止;零服务器成本,不支持的浏览器自动隐藏。
- 语音输入(STT):输入框新增麦克风按钮(Web Speech API),边说边出字,识别结果进输入框可再编辑;浏览器不支持时按钮隐藏。
- 斜杠指令:输入框以
/开头浮出指令菜单(翻译 / 总结 / 润色 / 扩写 / 解释 / 代码审查 / 续写 / 大纲 / 优化提示词),支持关键字过滤与 ↑↓ 选择,回车回填模板。 - 提示词优化器:把口语化提问用 AI 改写成结构化提示词,先弹「修改前 / 修改后」对照,确认才替换输入框,随时可放弃。
- 截断续写:回复因达到输出上限被截断(
finish_reason=length)时,消息操作栏出现「继续生成」,从断点接着写进同一条消息(OpenAI / Anthropic / Responses 三种格式都识别)。 - 消息收藏:AI 回复操作栏新增 ★,收藏随账号云同步;用户菜单「我的收藏」可查看、复制、跳回原对话、删除(上限 200 条)。
- 每日摘要:每天首次打开时展示一张「昨日概要」卡片(调用量 / 消耗 / 昨天聊过的会话,点击直达),服务端惰性聚合,不需要常驻进程。
账号与安全
- 两步验证(TOTP):设置 → 账户里可绑定验证器(纯 PHP 实现 RFC 6238,兼容 Google / Microsoft Authenticator 等);开启后登录密码正确也不发令牌,改发 5 分钟有效的中间票据,输验证码换正式会话。验证码错误走同一套登录失败锁。后台可关闭「新绑定」(已开启者不受影响)。
- 新设备登录提醒:登录成功且设备指纹(UA)与上次不同时发提醒邮件;同一设备重复登录不触发。邮件走新增的提醒队列(
data/mailq/),在 shutdown 阶段事务外投递,SMTP 卡死不影响任何写事务,失败自动重试 3 次。
管理端与运营
- 管理员操作审计日志:保存平台设置 / 用户增删改 / 调额度 / 备份恢复 / 强制下线 / 清日志 / 套餐增删 / 在线更新等管理动作全部记入日志(
kind=audit),后台「日志」新增「审计」筛选。 - 额度预警:后台设置阈值后,用户剩余额度低于该值时自动发提醒邮件(24 小时最多一次),在结算扣费路径里检查。
- 用户用量页 14 天趋势:设置 → 用量新增逐日调用柱状趋势条(纯 CSS,与既有消耗总结 / 模型占比同屏)。
笔记
- 笔记云端版本历史:编辑保存时把快照同步一份到云端(每笔记最多 5 份、单份 40KB、5 分钟内连续保存合并),「历史版本」弹窗新增「云端版本」区,换设备也能恢复。
- 分享页留言:分享对话框新增「允许访客留言」开关;
/n/<token>分享页出现留言列表与发表框(按 IP 限流、上限 100 条),「已分享管理」里可查看与清空。
主题
- 方块主题 Apple 官网化:SF 风格字体栈与抗锯齿排版、侧栏 / 输入区 / 弹窗改用饱和度提升 + 高斯模糊的半透明材质(apple.com 导航同款配方)、按钮全部胶囊化(980px 圆角)与顺滑按压反馈、空态大标题用产品页级字号与字距。原有「圆角矩形分块 / 不画任何分割线」的立论与全部几何断言保持不变。
- 后台可设置站点默认主题:平台设置新增下拉(TinyChat 默认 / ChatGPT 风格 / 方块 / Claude 风格),对新用户与从未自选过主题的用户生效(登录页与主应用都会应用),用户自己选过主题则以用户为准。
对话效率
- 快捷键扩充:
Ctrl/⌘+K改为聚焦会话搜索(原「新建对话」移到Ctrl/⌘+Shift+O)、Ctrl/⌘+,打开设置、?(非输入态)呼出快捷键速查表。 - 会话右键菜单新增「导出 Markdown」:不用进「设置 → 数据」也能把任意一条对话存为
.md。
测试
- 新增
tests/new-features.php(TOTP RFC 6238 已知向量 / 邮件队列 / 记忆去重与上限 / 收藏分片 / 笔记云端版本分片往返 / 额度预警阈值与冷却 / 审计条目 / 新设置项归一化)接入 CI。 - 新增
tests/new-features-contracts.js(mfa 票据两端消费 / 记忆注入走tc_append_system_text/ 收藏与续写接线 / 默认主题应用条件 / extras.js 挂载)接入 CI。 - 新增
tests/new-features-gui.mjs(真 Chromium:TOTP 绑定走真端点 / 收藏亮星与面板 / 斜杠指令回填 / 快捷键速查 / 继续生成按钮 / 默认主题不破坏外观)接入 CI。
TinyChat v2.0.164 供应商密钥填错不再把用户踢出登录
修一个会直接把用户踢出登录的缺陷。
修复
- 供应商密钥填错不再导致前台自动退出登录:后台添加供应商时 API Key 填错,前端发消息会立刻被登出并跳回登录页。原因是上游对错误密钥返回 401,而本站的供应商代理把上游状态码原样透传;前端拿到 401 会按「登录已过期」处理 —— 清空本地令牌、吊销会话。现在所有来自上游的认证 / 权限 / 配额类状态(401/402/403)在回传前统一归一为 502(上游网关失败),错误原文仍然保留在提示里供排查;本站自身的「未登录」「额度不足」「无权限」判定不受影响,真正需要重新登录时该 401 依旧会发出。涉及对话(含流式)、生图、生视频与文档解析各条出站路径。
测试
- 新增
tests/upstream-status.php(上游 401/402/403 归一为 502、429/5xx 保持原样、字符串状态同样按整数判定)并接入 CI。 tests/e2e.sh新增「密钥错误的响应状态」一组:坏 Key 的对话 / 流式对话 / 生图都必须返回 502 而非 401,同时回归断言未登录与无效令牌仍是 401。
TinyChat v2.0.163 AI 改写对照面板增加「在选中后追加」+ AI 处理进度条
[2.0.163]
承接 2.0.162 的 AI 改写对照预览,补两处使用中暴露的问题:改写结果只能替换、不能保留原文;以及右键跑动作时等模型返回那几秒没有任何反馈,像「点了没反应」。
新增
- 对照预览新增「在选中后追加」:选中文字跑 AI 编辑后,对照面板底部现在是三个按钮 ——
放弃/在选中后追加/替换选中内容(主按钮)。「在选中后追加」把模型结果插到选中文字之后、原文照旧保留,适合「扩写 / 总结」这类想留底稿的场景;追加位置同样先校验选区未变,定位失效时退回光标处,不会扔到文末。 - AI 处理进度条:所有 AI 动作(选区编辑、全文动作、列表页生成标题 / 标签 / 摘要、续写、日报)执行期间,笔记页顶部居中显示一张进度卡片 —— 转圈 + 「AI 正在<动作>…」文案 + 不确定进度条,模型返回后自动消失。此前只有右下角一枚小胶囊,等模型那几秒几乎看不见,用户会以为菜单点了没反应。
文档
- 修正 2.0.162 更新说明里「笔记列表页右键菜单」的措辞:列表页那组 AI 动作实际挂在笔记行尾的「⋯」按钮上(悬停笔记行才浮现),正文选区的 AI 编辑才是右键;README 同步订正。
测试
tests/notes-ai-interactions-gui.mjs扩充至 37 项:新增「执行 AI 动作后立即出现进度条、带不确定动画条、文案标明动作、返回后自动消失」,以及「在选中后追加保留原文、正文变长、结果落在选中文字之后」两组断言。
TinyChat v2.0.162 笔记列表页 AI 动作 + AI 改写「改前改后」对照预览
[2.0.162]
笔记页的 AI 交互从「先打开笔记才能用」扩到「在列表上直接用」,并给破坏性的 AI 改写补上「改前改后对照」这一关。
新增
- 笔记列表页右键菜单新增「AI」分组:不必先打开笔记,直接在列表项上跑
生成标题(依正文起名,确认后才替换)、推荐标签(自动补充标签,与已有标签合并去重)、生成摘要(写入正文开头)。三项与编辑器内的同名动作共用提示词口径与每日配额。 - AI 改写统一走「修改前 / 修改后」对照预览:选中文字跑 AI 编辑(扩写 / 谬误检查 / 总结 / 翻译 / 降低重复率)、以及全文的
写入摘要/生成大纲/提取待办/生成双链图谱,结果先弹左右对照面板,点「应用」才写回正文,放弃则一字不动。此前这些动作会直接改写正文,选错动作只能靠 Ctrl+Z 挽回。
变更
- 选区 AI 编辑由「结果插到选中文字之后、原内容保留」改为「预览后替换选中文字」。改写类动作的本意是替换,保留原文再追加实际上让正文越改越长;现在替换前会校验选区在预览期间未被改动,极端情况下退回光标处插入而不是错位覆盖。
showTidyPreview(原只服务「自动整理」)泛化为通用的showAiDiff(opts),上面所有预览入口共用一套弹窗与settled关闭守卫。
测试
tests/notes-ai-interactions-gui.mjs(新增):真 Chromium + 真服务端锁住 6 组行为 —— 列表菜单含「AI」分组且原有项不被破坏;列表「推荐标签」真的落进笔记tags;列表「生成标题」必须经确认框且确认后标题更新;选中文字 AI 编辑必须先弹对照预览、应用前正文不变、应用后选中处被替换;「写入摘要」整篇动作同样先预览再应用;全程无未捕获异常。
TinyChat v2.0.161 支持无 Key 上游 / 内网本地模型开关,出站代理补全 SOCKS
[2.0.161]
补上 2.0.160「API Key 可留空」未能真正打通本地 Ollama 的缺口:Key 那关过了,但发请求前的 SSRF 防线仍会挡住本地地址(127.0.0.1、192.168.x.x)与非白名单端口(Ollama 默认 11434)。现在提供后台开关。
新增
- 后台「对话设置 → 允许供应商指向内网 / 本地地址」开关(默认关闭):开启后供应商 Base URL 可指向内网 / 本地地址与任意端口,用于对接本地 Ollama / LM Studio(
http://127.0.0.1:11434)。关闭时行为与之前完全一致 —— 只允许公网地址且端口限 80 / 443 / 8080 / 8443。默认关闭,公网多租户部署无需改动、安全性不受影响。- 开关与出站代理同一手法:值在
tc_with_db里随库带进全局(SSRF 判定在事务之外、发请求前执行),另有环境变量TC_ALLOW_PRIVATE_UPSTREAM=1作为部署级来源(两者任一为真即放行)。 - 演示管理员不可修改该设置(回滚前已可用于探测内网),与 SMTP / 内容安全同一口径拒绝。
- 开启后仍守底线:带
user:pass@的 URL、非http(s)协议、空主机照旧拒绝。
- 开关与出站代理同一手法:值在
测试
tests/private-upstream.php(新增,已接入 CI):默认关闭时本地 / 内网 / 非白名单端口被拒、公网地址照常放行;开启后放行本地与任意端口,但仍拒绝带凭据 URL 与非 http(s) 协议;环境变量来源(子进程验证);设置归一化只认布尔真值、缺省为假。tests/e2e.sh:新增开关默认关闭 / 可开启 / 可回读 / 可关回四项,以及「演示管理员不可改内网访问设置」一项。
文档
- README / 上一版本的更新说明中「对接本地 Ollama」一句此前过度承诺(只去掉 Key 校验,SSRF 防线仍会挡),现已补上「需在后台开启内网放行」的前提。
[2.0.160]
两条来自使用的诉求:接入本地 Ollama / LM Studio 这类不需要 API Key 的上游时,保存供应商被「API Key 不能为空」挡住;以及出站代理想要 SOCKS 与更完整的代理类型支持。
新增
- API Key 可留空(无鉴权上游):新建 / 编辑供应商时不再强制填写 Key。留空即表示上游不需要鉴权,请求不会发送
Authorization/x-api-key头(而不是发一个空的Bearer,后者在部分网关会被判成「带了无效凭据」而拒绝)。适合本地 Ollama、LM Studio、或自建的无鉴权网关;填了 Key 的行为完全不变。注意:这只是去掉保存时的 Key 校验,要让供应商地址真正指向本机还需开启下方 2.0.161 的内网访问开关。 - 出站代理支持完整类型:此前只显式支持
http/https/socks5/socks5h,现在补上socks4与socks4a,并把 scheme 到 curl 代理类型的映射收口到一个函数(tc_curl_apply_proxy),按 scheme 设置CURLOPT_PROXYTYPE(socks4a/socks5h由代理解析域名)。后台「对话设置 → 出站代理」的输入校验与提示文案同步更新。
变更
- 出站代理覆盖面收敛到「全部出站请求」:代理此前只在统一助手
tc_http_request里生效,另有 9 处直接curl_init的旁路(在线更新检查与下载、在线浏览器抓取与子资源预热、搜索结果并行抓页、SearXNG 探测、图片留存下载、图片代理、视频代理)不走代理 —— 表现为「配了代理,但某些功能仍直连、在国内网络卡死」。现在这些路径统一调用同一个tc_curl_apply_proxy,配了代理就全都走代理。 - 获取模型列表 / 测试连通性 / 网页 AI / IM AI 的空 Key 处理:这些路径此前对空 Key 直接拒绝(
请先填写 API Key等),现在允许空 Key 直连(地址仍必填),只在带了掩码占位符••时才清空后按无 Key 处理。生成的图片 / 视频请求同理:空 Key 不再发送Authorization头。
测试
tests/outbound-proxy.php(新增):scheme 到 curl 代理类型的映射(含大小写不敏感、未知 scheme 返回 null、remoteDns标记)、端到端断言实际写入的CURLOPT_PROXY/CURLOPT_PROXYTYPE、非法代理串(ftp/file/javascript:/socks6)被拒、未配置时不写任何代理选项。已接入 CI。tests/e2e.sh:新增「无 Key 供应商可保存」「hasKey 为假」「可正常对话」三项;原先「缺 Key 被拒」的断言改为「缺 Key 直连无鉴权上游成功」。
2.0.159
修复
- 模型偏好跨设备同步后静默失效:默认生图 / 生视频模型、AI 工具判定模型、跟进建议模型、笔记辅助模型这些偏好,值都形如
providerId\nmodelId(换行分隔供应商与模型)。服务端的云同步清洗tc_settings_text()把换行当控制字符一并剔除,两段被粘成providerIdmodelId—— 跨设备同步回来既找不到供应商也找不到模型,该偏好悄悄失效(本机不经清洗,所以只有换设备才暴露)。现在为这类偏好新增tc_settings_model_ref():保留换行分隔符,其余控制字符照旧剔除,并归一化为「供应商 + 模型」至多两段(去空段、去首尾空白)。普通短文本的清洗行为不变。
测试
tests/settings-sync.php新增 9 项:直接对清洗函数下探(保留换行、去首尾空白、丢空段、空值归空、普通短文本仍剔除换行未被波及),并在 sanitize 白名单用例里同时覆盖prefs与ui两侧的模型引用键。tests/settings-sync-gui.mjs新增 5 项:走真实云同步链路写入providerId\nmodelId,断言云端落库带换行,再用全新浏览器上下文(新设备)登录同一账号,断言偏好与界面两侧的模型引用都带换行恢复。
2.0.158
四条来自使用的反馈:侧栏那个开关样式乱了、生图生视频按钮应该自动列出可用视频模型、后台更新日志要支持 Markdown、以及开关式地开启自动更新(默认开启)。
修复
- 侧栏「简单对话 / 多角色」的开关样式错乱:
style.css为挡住.field span{display:block}给.switch钉了min-height:26px,而groupui.css里的缩小版只覆写了height:20px——min-height恒压height,轨道被撑回 26px 高,旋钮却还是 14px,于是胶囊里空出一大截(用户截图里那个)。现在缩小版把min-height一并覆写成 20px,实测旋钮四周留白恒为 3px。 - 生图 / 生视频入口的下拉只列当前供应商的模型:入口在「任意供应商有该类模型」时就会出现,而弹窗与下拉此前只扫当前供应商 —— 当前对话供应商恰好没有视频模型时,点开下拉是一片空白。现在候选跨供应商汇总,条目显示成「渠道@模型名」,选中后按所选模型的供应商路由(请求里的
providerId不再固定为当前供应商)。没有可用视频模型时给出明确提示而不是空弹窗。
变更
- 后台「版本更新」的发布说明渲染成 Markdown:发布说明是 GitHub Release 的 body,本身就是 Markdown,此前直接塞进
<pre>显示一堆#/*/ 反引号。现在交给全站同一套渲染器(经 DOMPurify 消毒)渲染成标题、列表、加粗、行内码与链接,并补上后台语境下的排版样式。 - 新增「自动更新」开关(默认开启):在后台「版本更新」面板可切换。开启后打开该面板时若发现新版本会自动执行更新(与「一键更新」同一条下载 / 校验 / 备份 / 加锁流程,更新前照常自动备份);关闭后仅提示,需手动点「一键更新」。只在打开面板时触发,手动点「检查更新」不会顺手升级。
- 「≡」菜单里生图 / 生视频行右侧新增模型下拉:候选与弹窗、设置里的「默认生图模型」共用同一份偏好(生视频新增
videoModel偏好并纳入云同步),选中即记住;未选中时展示自动挑出的模型,让用户一眼看到会用哪个。该行拆成「动作按钮 + 模型下拉」两个可点区域(下拉不能嵌在按钮里)。
测试
- 新增
tests/media-toggle-gui.mjs(20 项):真浏览器量侧栏开关的轨道高度与旋钮留白,并构造「当前供应商只有对话/生图、视频模型在别的供应商」的场景,验生图/生视频下拉列出跨供应商的全部可用模型、不含对话模型、选中后落到正确供应商、偏好落库、弹窗默认选中同一个模型。 - 新增
tests/update-panel-gui.mjs(17 项):预置检查缓存(不触网)验发布说明渲染成<h2>/<li>/<strong>/<code>/<a>且原始 Markdown 记号不漏出;验「自动更新」默认开启、切换后真的落库(重读接口仍是新值),而不是只改前端勾选。 - 两者都已登记进 CI。
本次回归:19 套 PHP 自检、13 套 JS 自检、GUI 全量(含新增两套)、隔离端口端到端 630 项、模型汇总端到端 44 项通过;发版产物重复生成无差异。
2.0.157
修复
- 中文字体切换往返即时生效:思源宋体与阿里巴巴普惠体的切片样式表共用同一个族名;此前两份样式表只增不减,切回已加载的字体仍被后插入的样式表覆盖。现在只保留当前选中的中文字体样式表,切到系统或本机字体时移除网页字体样式表。保留缓存与按需分片下载,未修改字体文件或字形。
- 注册协议勾选框与文字同行:原来的协议行只有 flex-direction,没有 display:flex,实际仍是 .field 的块布局。两处注册入口改用专用横向布局、固定 16px 勾选框,文字可在自己的列内换行。
- 纠正 2.0.156 对汇总标签位置的误解:用户要求的是模型选择器顶部的渠道标签,不是回答版本标签。所有汇总模型集中到「全部」后面的第一个渠道标签「自动切换」,使用平台 logo;列表与选中项显示 Auto@模型名。普通渠道和用户自己添加的模型照旧显示,底层 agg: 路由不变。撤回单个汇总回答强制显示回答版本标签的改动。
测试
- 字体往返用实际选择器操作并核验 Chromium 真正渲染的中文字形,而不仅检查偏好或 CSS 字符串;覆盖思源宋体、普惠体、系统字体、本机字体和刷新后的恢复。
focus-ring-gui.mjs共 151 项:字体实际渲染、两处注册入口、14/22px 字号、桌面/窄屏、标签点击与协议关闭后的隐藏。model-groups-gui.mjs共 70 项:统一自动切换标签、平台 logo、多个汇总模型、搜索过滤、用户渠道独立及真实选中路由。
本次回归:19 套 PHP 自检、13 套 JS 自检、20 套 GUI 全部通过;隔离端口端到端 630 项、模型汇总端到端 44 项通过。发版产物重复生成无差异。
2.0.156
2.0.156
四条来自使用的反馈。最后一条查下去发现根源比预想的严重:后台「成员渠道」那个窗口的样式一条都没有。
后台「成员渠道」窗口:此前没有任何 CSS
JS 一直在生成 ma-pick / ma-pick-row / ma-pick-prov / ma-tag / ma-member / ma-card / ma-ops 这一整套类名,但样式表里查无此类(同一个后台的「模型元数据」mm-* 有 50 条规则,这边是 0 条)。于是勾选框和文字挤在一起、渠道分组与模型行没有层级、按钮堆成一团 —— 你看到的「乱七八糟、各种没对齐」就是这个。现在补齐了这一族样式:渠道分组吸顶 + 底色、每行统一 34px 行高、勾选框固定 16px 并真正垂直居中、成员选择器限高滚动、卡片与状态标签按站内设计系统(无描边,分层靠底色与 hairline 内阴影)。
开关白点溢出胶囊(截图里那个)
.switch 是 <span>,而 style.css 里有一条 .field span { display: block; font-size: .929rem } —— 开关一旦落在 .field 里就被压成行盒高度(height: 26px 失效,实际 20px),而绝对定位的旋钮仍是 20px + top: 3px,于是底部溢出 3px、右侧看起来也对不齐。现在把盒模型和尺寸钉死,实测旋钮四周留白恒为 3px。
同时修掉两处同源问题:
- 生成汇总弹窗里的非法 HTML:那段是「
<label class="field">里又套一层<label class="user-form-admin">」的嵌套 label(模型元数据弹窗里也有同样写法)。嵌套 label 不是合法结构,浏览器会把关联关系打乱。外层已改成div。 - 勾选框与模型名错开 3px:同一条
.field span { margin-bottom: 6px }漏进了选择器行内的<span>,把文字整体上推。清掉后实测偏差 0px。
汇总不再收纳用户在前台自己添加的模型
汇总的成员池此前扫的是全部供应商,没有区分「平台渠道(管理员添加)」与「用户自建」。两个后果:用户自建的一条同名渠道就能把「只有 1 个平台成员」的模型顶成 ≥2,凭空造出一条全局汇总组(而该组对其它用户只有一个真实成员);而该用户的同名模型本就在他自己的列表里,再被汇总收纳一次,他反而找不到自己那条渠道了。
现在建组、成员解析、成员校验三处口径统一为「只认平台渠道」;后台弹窗把用户自建渠道单独列成只读清单(带渠道主),说明为什么它们不参与汇总。
其余两条
- 生图留存文件与数据备份清单默认折叠 + 分页:这两份清单会随使用不断变长(留存按张、备份按天累积),此前平铺渲染会把整页撑得很长。现在默认收起(标题上直接写明「多少个 · 多大」,不展开也知道规模),展开后固定限高内滚动、每页 10 行并带翻页。
- 汇总模型回答在对话里只占一个标签,名字是
Auto@模型名:汇总的意义就是「多个渠道一个 ID」,一轮回答只该有一条标签,而不是每个成员渠道各占一条。logo 由模型名匹配,同一个汇总 ID 背后可能是不同厂商的模型,图标据此自动切换;汇总只有一条回答时也会画出标签条(此前要 ≥2 个版本才画),否则看不出这一轮是哪条汇总 ID 答的。
测试
tests/model-groups-gui.mjs39 → 52 项:新增排版几何断言(勾选框与文字中心偏差 ≤2px、行高一致、分组标题吸顶、选择器限高、旋钮不得溢出轨道)与汇总回答的标签断言(有且只有一条、名字是Auto@agg-model、带 logo、不泄漏agg:前缀)。这几条抓出的正是上面那些渲染缺陷 —— 接口全对,界面却是错的。- 新增
tests/storage-panel-gui.mjs(22 项):写 25 个留存文件 + 14 个备份文件,真浏览器里验默认收起、标题写明规模、一页 10 行、翻页真的换内容、末页「下一页」禁用且正好装下余数、限高可滚动、再次收起不占高度。 - 两者都已登记进 CI。
回归:PHP 20 套、JS 静态 13 套、GUI 全量 18 套零失败(含 model-groups-gui 52 / storage-panel-gui 22 / chat-api-group-gui 50 / local-store-gui 39 / settings-sync-gui 27 / toolbox-gui 187)、e2e.sh 630 项、model-groups-e2e.sh 44 项、release.mjs 幂等。
本版无数据库迁移,替换文件即可。