Releases: zeroa234/ryza-ai-revive
Release list
Ryza Chat 1.2.22
存档槽从 1.2.19 起就是坏的;报错不再说中文;缺图不再沉默
这一版修的是反馈里最要命的一条:1.2.19 / 1.2.20 / 1.2.21 三个版本的存档槽完全不能用
(按了「保存」什么都不写,槽位一直显示「空槽」,提示却照样说「已保存」)。另外把
「填错接口地址就一直转圈」和「脱衣 404 但什么都不说」也一并处理了。
Downloads
RyzaChat-Setup-1.2.22.exe—— Windows 安装包RyzaChat-1.2.22.apk—— Android(versionCode 25)
修了什么
1. 存档槽存不进去也读不出来(issue #6)
根因:SAVE_KEY 这个存储键只声明在 app.js 的闭包里,而真正使用它的两处代码在
settings.js(拆分文件时声明没跟着走)。两处调用都包在 catch (e) {} 里,
ReferenceError 被吞掉 —— 于是列表永远渲染「空槽」,写入永远丢失,按钮仍然提示「已保存」。
- 影响:1.2.19 / 1.2.20 / 1.2.21 三个版本,浏览器 / Electron / 安卓三端全部如此。
- 没有数据损失:因为从来就没有写进去过(设置、角色档案、对话历史一直是自动保存的,不受影响)。
- 修法:键声明归位(并删掉 app.js 里那份死副本);写入失败不再谎报成功——会说明原因
(最常见是本机存储配额,一个槽要装下整段对话历史);读到残缺存档也会说明,而不是静默返回。 - 新增
scripts/save_slot_regression.js:真的去按那两个按钮,断言字节确实写进 localStorage、
刷新后还在、读取能还原;并带反向对照(把声明删掉必须复现旧 bug)。
2. 填错接口地址就一直转圈,而且报错是中文(issue #11)
最可能撞上的两条传输错误(请求超时 / 网络请求失败)原来是写死在 api.js 里的中文,
10 处;而错误分类只能用文案去猜,这两条谁都匹配不上 —— 面板于是只说「现在连不上,待会再试」,
用户就会一直重发,而不是去改设置。现在:
- 文案按界面语言出词(英语 / 印尼语玩家不会再看到中文);
- 错误类型挂在错误对象上,提示与面板台词直接点名最可能的原因:接口地址必须以
/v1结尾、
模型名要对得上; - 新增
scripts/transport_error_regression.js(真的触发超时 / 断网)。
3. 脱衣 404:不是缺图,是什么都不说(issue #4)
先核了发行包:crf_skn_002_0001_99nsfw.png 本来就在包里。日志里 404 的是加载器的第三个
候选文件名(..._99_nsfw.png),说明前两个候选先失败了 —— 那是从源码跑、没有跑
restore_media 的情况。真正的问题是这个失败完全静默:渲染层按设计留在默认贴图,
于是唯一的证据是控制台里的一条 404。现在会告诉你是「这套服装没有对应贴图」还是
「素材可能没还原」,并点名 scripts/restore_media.py。
4. 顺手清掉的中文写死文案
举报者截图里那两个中文按钮(印尼语界面下的「保存并回到对话 / 清空对话记忆」)以及它们周围的
确认框、提示,全部进了 i18n,7 种语言齐了。
5. 新增入门指南 docs/SETUP.md
回答 issue #6 / #11 / #2 / #12 反复问的那套:要填哪两个 Key、接口地址为什么必须 /v1
(附 OpenRouter / Ollama / LM Studio / Qwen / DeepSeek 的可用地址表)、Fish Audio 两套接口
与免费引擎、为什么安卓上跑不了本机模型、ASMR 是对话模式而不是服装、存档槽在哪、
以及源码跑要补 restore_media。英文正文 + 印尼语摘要。
验证
- 套件:17 个 node 回归 +
layering_check --strict+privacy_check全绿(新增 2 个套件,
并扩充了 boot_smoke 与 nsfw_intent_regression)。 - 真浏览器走查(Edge,印尼语,复刻举报者的操作):三个空槽 → 点「Simpan di sini」→
真的写入 → 刷新页面后槽还在 → 点「Muat」正常还原回对话;底部按钮全为印尼语,无中文残留。
English
Fixed a save-slot bug that shipped broken in 1.2.19 / 1.2.20 / 1.2.21 on every host
(the storage key was left behind in another module's closure, the failure was swallowed, and the
button still said "Saved"), made a wrong base URL say so instead of spinning forever, and made a
missing outfit texture say so instead of leaving a 404 in the console. New first-run guide:
docs/SETUP.md.
Ryza Chat 1.2.21
Fish 语音修好了 —— 真因不在 URL,在代理
这一版主要修玩家反馈的四个问题,其中三条是同一个根因。都是能复现、能定位到代码行的真 bug。
Downloads
RyzaChat-Setup-1.2.21.exe— Windows 安装包RyzaChat-1.2.21.apk— Android(versionCode 24)
修了什么
1. Fish Audio「留空不行、填 api.fish.audio 也不行」
根因:三个宿主(浏览器调试服务器 / 桌面壳 / 安卓壳)的 /_proxy 只转发
Content-Type、Authorization、api-key 三个头,把 Fish 的 model 头吃掉了。
Fish 现在这套接口(POST https://api.fish.audio/v1/tts)把引擎名放在请求头里
(model: s2.1-pro-free),头一丢,Fish 就只能回退到付费引擎,回一句
402 Insufficient API credit —— 所以不管你 URL 填什么、填不填,走打包版都不可能成功。
旧版 Open API 把引擎名写在 body 里,所以它一直能用,问题只在现役接口上。
三端都已同步转发这个头,并且加了一条回归测试:它用一个真实的 echo 上游服务器
断言这个头真的到达了对端(不是读源码),也验过「去掉转发就会失败」。
同一轮里还实测出另外三件事(用真 key 打官方接口):
| 现象 | 之前的行为 | 现在 |
|---|---|---|
| 把接口地址留空 | 解析到 fishaudio.org —— 这是个同名不同家的站点,同一把 key 打它会回 401 |
留空 = 官方 https://api.fish.audio |
| 音色 ID 留空 | 直接报错「需要先建好音色」,等于把「填了 key 就能说话」这条路堵死 | 实测不带 reference_id 也能拿到音频,现在就用 Fish 自己的默认音色 |
| 换了付费引擎 / 引擎名写错 | 只有一句通用报错 | 明确说「免费只有 s2.1-pro-free,报 402 就是这个原因」 |
另外:旧版部署仍然照旧(填它的地址就能用,绝不偷偷改写你填的地址),
只是错误信息会点名这两个同名站点。出厂默认的引擎名也跟接口对齐了(老存档会一次性迁移)。
新增:ASMR 单独配置音色 ID(设置 → 语音合成 → Fish 区块「Fish ASMR 音色 ID」)。
填了它,ASMR 模式用这个音色、其它模式用「Fish 音色 ID」;不填就都用普通音色。
2. 安卓「导入服装点了没反应」
App 里只有一个录音权限,导入按钮点了像没反应 —— 其实不需要存储权限:
安卓的 WebView 自己不实现文件选择器,宿主必须实现 onShowFileChooser,而它当时没实现,
于是点击变成了静默空操作。现在实现了(走系统的文件选择器,单次授权、不申请任何存储权限),
选完的 ZIP 会正常进索引并提示「已导入」。
3. 安卓「+ - 只能缩放背景、立绘不能拖、还没法收回去」
- 缩放:原来缩放后的画面窗口也被拿去做立绘摆位,那里的换算刚好把立绘的放大又除了回去
—— 屏幕上就是「背景变大、莱莎不变」。现在缩放只作用于镜头投影,整幅画面(含莱莎)一起缩放。 - 拖动:立绘现在可以用手指拖动(在可见范围内,有边界限制),轻点仍然是分部位互动。
- 收起:右侧按钮列最上面多了一个 ✕,点一下整列收起(只留那个小键,再点展开),
收起状态会记住。
4. 安卓「少了站立/坐下按钮」
先核过:按钮就在 1.2.20 的包里,也没有安卓专有分支 —— 真正的原因是它的显示条件绑在
「这张地图是否同时支持两种姿态」上,而官方 200 组「地图 × 时段」里 196 组只标了坐姿,
所以新装玩家基本永远看不到它。
现在改成由穿着的服装决定(官方包里只有那套基础服装同时有坐姿和站姿两套骨骼;
ASMR 泳装只有坐姿、导入的 ZIP 也只有一种)—— 只有真能切换时按钮才出现,
不会出现「切一下姿态顺手把衣服也换掉」。站姿仍是默认,换地图会回到站姿。
服装页也补了一行说明,告诉你在哪里切换。
Ryza Chat 1.2.20
两个来自 issue 的修复
这一版只做修 bug。两条都是用户报的、能复现的真问题;其余 issue 由 1.2.19 的内容覆盖(见文末)。
Downloads
RyzaChat-Setup-1.2.20.exe— Windows 安装包RyzaChat-1.2.20.apk— Android(versionCode 23)
修了什么
1. 本机跑模型不再被拒(#5:Chat failed: proxy target must be https)
想用 Ollama / LM Studio / llama.cpp 的人全都撞在这条上:这些引擎在本机 127.0.0.1 上用明文 http,而三个宿主都硬性要求 https —— 于是"本地优先"这个最正当的用法,恰好是唯一被拒的那个。
现在的规则是:https 任意,http 仅限 loopback(127.0.0.0/8、localhost、::1)。所以:
http://127.0.0.1:11434/v1✅ 可以用http://192.168.1.5:11434❌ 仍然拒绝(例外是 loopback,不是"内网段")http://127.0.0.1.evil.com❌ 仍然拒绝(只看名字前缀是不够的,这里按点分四段解析地址)
三个宿主(dev 服务器 / Electron 主进程 / Android AssetServer)实现同一条规则,由 config/layers.json 的契约钉住,scripts/proxy_target_regression.js 逐例核对 Python 与桌面两份实现、并真起 dev 服务器打端到端;它同时守一件事:桌面壳里每个 require() 都必须在打包清单里(否则会出现"源码能跑、装完才炸")。
2. Fish Audio 现在两套接口都能走(#7,以及 #6 里的同一条)
Fish 在野外有两套接口,用户各踩各的:
| 旧 Open API | 现役 | |
|---|---|---|
| 入口 | /api/open/v1 + POST /speech/tts |
https://api.fish.audio + POST /v1/tts |
| 引擎写在哪 | 请求体(voiceId / modelId) |
请求头 model(如 s2.1-pro-free) |
| 音色 | 可用本地样本自动克隆 | 需先在 fish.audio 建好,填它的 id |
以前把用户填的 api.fish.audio 静默改写成旧 host —— 等于把 key 送到一个它不工作的地方,然后报一句看不懂的通用错误。现在:
- base URL 决定走哪套,不再被改写;默认仍是旧那套(所以原先能用的配置一个都不会被弄坏)。
- 401 / 403 / 429 现在说清原因并带状态码,错误体里回显的 key 会被打码。
- 音色列表跟着走(新版
/model,旧版/voices),模型建议里也补上了新版的s2.1-pro-free/s2-pro/s1。 - 设置页提示(七种界面语言)写清了两套接口的区别,以及"自动克隆只在旧版可用"。
谁该升级
- 用本机模型(Ollama 等) → 必须升,否则根本连不上。
- 用 Fish Audio → 建议升:如果你填的是
https://api.fish.audio,之前一定失败;升完就能用。 - 用云端 OpenAI 兼容接口、且不碰 Fish 的人 → 没有行为变化,升不升都行。
校验
- 两包都过打包前后两道隐私闸门,不含
config/providers.json、个人端点、测试音频。 - APK 由 aapt2 读出
versionCode 23/versionName 1.2.20;web/js与源码逐字节一致。 - Android 侧的 proxy 规则改动确认编进了
classes.dex(新错误文案与proxyTargetAllowed/isLoopbackHost都在);桌面侧的规则模块proxy-target.js确认在app.asar内,不会出现"装完才 require 失败"。 - 15 个回归套件 +
layering_check --strict全绿。
升级须知
- NSFW 默认关闭,只能在设置里手动打开。
- 存档路径不变:
%AppData%\RyzaChat\ryza-web-storage.json,覆盖安装不会丢。 - 如果你是从 1.2.15 或更早直接过来,中间跳过的四个版本的完整变更在 1.2.19 的说明 里(官方皮肤、世界地图重做、服装导入、长期记忆、语音输入与闹钟、NSFW 权限开关、Android 返回键……)。
Ryza Chat 1.2.19
上一个 Release 是 1.2.15 — 中间跳过了 1.2.16 / 1.2.17 / 1.2.18
如果你是从 1.2.15 直接升上来,这份说明按版本分段写全:先是四个版本的完整变更,后面是社区 PR、构建校验、以及升级须知。源码里也能逐个对照(config/version.json 是版本的唯一来源)。
Downloads
RyzaChat-Setup-1.2.19.exe— Windows 安装包(Electron,无边框窗口)RyzaChat-1.2.19.apk— Android(arm64,versionCode 22)
推理与语音不随包分发:装上后在设置页填自己的 OpenAI 兼容端点(对话 + 可选 TTS/STT)。
1.2.19 (code 22) — 官方内容落地 + 世界地图重做
官方 1.1.1 的数据与美术这一轮大量落地,世界地图整块重做。
官方内容
- 6 款官方皮肤:4 款付费皮肤从官方 CDN 拉取,sha256 与官方记录一致(
scripts/verify_skins.py可复核)。附带修正了此前关于 1.1.1 手势表的结论。 - 官方任务板形制:3 组 × 4 条,按天 0 / 3 / 5 开启,4 种活动计数器(
quests.js的Welcome;welcome_mission_regression.js守这个形制,防止被改回随意数值)。 - 官方坐姿表:读
SittingSets(官方权重全为 0 ⇒ 不自动切换)与SittingMandatorySlots(盘腿姿势强制占用 leg 槽)。 - 官方文案分段:译文以独立说话人进
npc.js,永不进 TTS(语音照旧读她的原句);设置里新增「有译文时同时显示原文」。 - 1.1.1 附带内容:rev2 手势表、新版登录美术、服务器数据、文本语料。
世界地图(重做)
- 三级形态:区域级(官方区域实图铺满 + 地名胶囊 + 位置标)/ 地点级(stage 标记)/ 区域弹层。
- 钉子按官方区域图标定;没标定的用确定性环形布局兜底(标定优先,
pin.dataset.calibrated可区分来源)⇒ 38/38 field、120/120 stage 全部可点,最近两钉间距 53px 不重叠。 - 地图模式底栏最右有列表切换键,双向可切(此前切进地图就回不了列表)。
- 官方
current_location.svg是空气泡,所以「目前位置」用 HTML 文字叠上去,不是贴图。
新功能
- 本地服装导入:ZIP → 校验(≤64MB / ≤64 条 / 单页 / Spine 4.2)→ IndexedDB → 直接穿上(
crfstore.js,端到端验证过真上传真穿)。 - 长期记忆:带日期的条目 + 摘要 + 相关度挑选,受保护条目不会被挤掉(
longterm.js)。 - 语音片段缓存:按字节预算逐出、收藏豁免;对话页可 ▶ 重播 / ★ 收藏(
voicecache.js)。 - 相机缩放:只放大 1.0–2.5(+-◎ 三个快捷钮 + 滚轮)。
- 自动手势调度:说话 1.8–3.8s / 闲置 3.8–7.4s,80/20 探索比例,最近 5 组去重,语义动作后让位 2.3s。
修复
- 每日登录提醒不再叠两条 toast(加了闸门 +
enterGame幂等)。 - 失败提示按原因分类,不再一律一句笼统报错。
- 标题页按键触控高度 44px;窄屏顶栏 9 个钮改横排,不再挤成一团。
- 渲染层不再认具体皮肤 id(解耦),换装/切姿态不会串到别的皮肤。
明确不做
- 眼睛高光保位:实测确认这套骨骼不需要(虹膜与高光同骨,
probe-eye-bones.js为证),所以不做——不是漏了。
1.2.18 (code 21) — 语音输入与闹钟
- 语音输入在实际发布的形态上可用:打包的壳(Electron / Android WebView)没有浏览器识别器,所以走客户端自己采集 PCM + 转写端点(OpenAI 兼容
POST /audio/transcriptions,multipart/form-data经/_proxy);浏览器里仍可用内置识别器。两个引擎后面是同一个闸门(半双工、冷却、文本回声抑制),规则一致。 - Android 闹钟真的会响:接入原生系统级排程,进程被杀也保留,前台火线回调;Web 侧的定时器让位,不再双重触发。
- 顺带修掉了 VAD 试验中发现的 MIME 缺口。
1.2.17 (code 20) — 复核轮 R1 / R2
上一轮交接说「全绿」,复核时逐条读代码,查出九处真实缺陷(其中三条是「文档说做了、代码没做」):
- 回声过滤从未生效:
echo.js接进了麦克风,但全仓没有任何地方调用remember(),文本回声抑制实际上只能回答「不是」。现在由合成端唯一漏斗Voice.noteAssistantSpeech()喂入。 - 其他角色说完后,莱莎那句会被标成对方的名字且不朗读:提示词承诺「无前缀的行是莱莎的」,解析器却按「接着上一位说」——解析器改成与提示词一致。
- 一次音频出错会让麦克风永久变聋:
playSpeech只在ended/abort 结算,加载失败或play()被拒时状态机永远停在「说话中」,而麦克风用「是否在说话」当闸门 ⇒ 麦克风再也不开。现在这两种失败都会结算。 - R2:每个概念只留一个归属者;版本检查也学会处理带连字符的版本号。
1.2.16 (code 19) — 语音层重建(S 系列)
这一轮把「说话」这件事从 app.js 里拆出来,并把模块边界变成机器强制的。
- S1 边界冻结:没有任何模块再向上引用,边界守卫转为严格模式(
config/layers.json+scripts/layering_check.js --strict:越层、环、core 纯度、三端/_proxy契约、版本字面量五项检查)。 - S2 谁在说话有唯一归属(
turn.js):意图队列(priority / queue / interrupt / replace)、播放取消、reply epoch —— 打断变成真的,不再是「等这句话说完」。 - S3 一个 provider registry(
providers.js):TTS 与 STT 一张表一行,凭据解析只有一个出口(openai/qwen/fish分区,换端点不会串用上一家的 base URL 和 key)。 - S4 对话的另一半:麦克风输入,带诚实的闸门。
- S5 onset barge-in:默认关闭的可选项——因为「诚实的失败」比「一个会误触的功能」更差。
- S6a
settings.js:设置页装配离开编排器(app.js2813 → 2194 行),入口名保持不变。 - S7 其他岛民终于能说话(
npc.js):多说话人协议、候选打分、交互频率。
社区 PR(本轮合入)
- #3 用户可控的 NSFW 权限闸门 — NSFW 变成「用户授权」而不是「角色扮演开关」:设置里关着时,模型输出再怎么说都不会脱;
undress:off永远恢复常服;默认关闭。- 合并时有个坑值得记:这个开关原本加在
App.buildSettings()里,而本分支已把装配搬到settings.js,如果直接「取我们这边」,功能会静默消失而所有测试仍然是绿的——所以是手工移植进settings.js的。
- 合并时有个坑值得记:这个开关原本加在
- #10 返回键先关菜单、再退出 — 这个 App 的每个菜单都是单页上的 DOM 覆盖层,WebView 历史永远是空的,返回键过去直接退整个 App。现在返回键先问页面:有层就关最上面那一层(弹窗 → 覆盖层 → 底部抽屉 → 侧边菜单 → 回到对话),没有层才退出;闹钟/昏倒这类覆盖层有自己的收尾(停声、标记完成),不是单纯隐藏。顺带补全了印尼语(此前只有零星几条,选印尼语时大半界面还是英文)。
- 该 PR 自带的 CI 工作流没有合入:
./gradlew assembleRelease在这份仓库里产不出能用的包(没有android/app/src/main/assets,web 树是构建后由pack_apk_assets.py打进去的;且没有签名配置 ⇒ 产物是未签名的空壳),还会绕过两道privacy_check闸门。Gradle wrapper 保留了。
- 该 PR 自带的 CI 工作流没有合入:
暂未合入
- #8 Fish Audio 端点改动:文档上确实是
POST https://api.fish.audio/v1/tts+ 请求头model,但用维护者的 key 实测该端点对 POST 一律401 Invalid Token(同一 host 的/model是公开的,所以它返回 200 不代表 key 有效),而仓库当前的通路(fishaudio.org那套 Open API)返回的是正常业务错误、配合已有配置可用。贸然替换会让现有 Fish 配置直接失效,所以留到能用有效 key 验证之后再决定。
构建与校验
- 两道隐私闸门都过:打包前扫
web/树 + 阶段产物,打包后再扫整个 APK 与桌面包。两个包里都不含config/providers.json、个人端点、测试音频。 - APK:
versionCode 22/versionName 1.2.19(aapt2 读出),3685 个资源、612.6 MB。 - 逐字节核对:
web/js与index.html等在两包内与源码 md5 一致(含本轮的back.js/settings.js/nsfw.js/worldmap.js)。桌面壳的 web 树在resources/web/(不在app.asar里,asar 只有 13 KB),所以是拿阶段目录核的。 - 回归:14 个套件 +
layering_check --strict全绿(boot_smoke、back_regression、game_logic、memory、longterm、sitting、welcome_mission、crf_import、motion、expression_coverage、stt、voice、electron_storage、nsfw_intent)。
升级须知
- NSFW 默认关闭,只能在设置里手动打开;AI 无法在你关着的时候自行开启。
- 存档位置不变:
%AppData%\RyzaChat\ryza-web-storage.json,覆盖安装不会丢。 - 从 1.2.15 升上来的话,中间跳过的四个版本都已经在包里,直接装这个即可。
Ryza Chat 1.2.15
Downloads
RyzaChat-Setup-1.2.15.exe— Windows installerRyzaChat-1.2.15.apk— Android