Skip to content

Releases: zeroa234/ryza-ai-revive

Ryza Chat 1.2.22

Choose a tag to compare

@zeroa234 zeroa234 released this 22 Sep 05:15

存档槽从 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

Choose a tag to compare

@zeroa234 zeroa234 released this 21 Sep 04:16

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

Choose a tag to compare

@zeroa234 zeroa234 released this 20 Sep 09:13

两个来自 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

Choose a tag to compare

@zeroa234 zeroa234 released this 20 Sep 08:38

上一个 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.js 2813 → 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 保留了。

暂未合入

  • #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

Choose a tag to compare

@zeroa234 zeroa234 released this 02 Sep 02:42

Downloads

  • RyzaChat-Setup-1.2.15.exe — Windows installer
  • RyzaChat-1.2.15.apk — Android