# Technical Documentation: triwinds/ns-emu-tools

> ℹ️ **Provenance:** Multi-Tier Ingestion · [CodeWiki Reference](https://codewiki.google/github.com/triwinds/ns-emu-tools)

### Overview (`readme.md`)

# Ns Emu Tools

一个用于安装/更新 NS 模拟器的桌面工具。

项目当前使用 **Rust + Tauri 2** 构建桌面端，前端使用 **Vue 3 + Vite + Vuetify**。







## 技术栈

- 桌面端后端：Rust + Tauri 2（`src-tauri`）
- 前端：Vue 3 + Vite + Vuetify（`frontend`）
- 前端构建产物：`web`

## Features

 - ~~支持安装 Yuzu EA/正式版模拟器~~
 - ~~支持 Yuzu 版本检测及更新~~ (yuzu 目前已经停止开发)
 - 支持安装 Ryubing/Ryujinx 正式/Canary 版模拟器及版本检测及更新
 - 支持安装 Eden 模拟器及版本检测及更新
 - Eden 下载源已切换到官方自建 Git 仓库
 - 支持安装 Citron 模拟器及版本检测及更新（Windows/macOS）
 - Citron 下载源使用官方 GitHub Releases
 - 自动检测并安装 msvc 运行库
 - 支持安装及更新 NS 固件至模拟器
 - 支持固件版本检测 (感谢 [a709560839](https://tieba.baidu.com/home/main?id=tb.1.f9804802.YmDokXJSRkAJB0xF8XfaCQ&fr=pb) 提供的思路)
 - 管理模拟器密钥
 - Yuzu 金手指管理
 - aria2 多线程下载

## 使用方法

### 一、使用预构建的版本运行

从 [GitHub 发布页(稳定版本)](https://github.com/triwinds/ns-emu-tools/releases) 或
[CI 自动构建](https://github.com/triwinds/ns-emu-tools/actions/workflows/ci-build.yaml) 下载可执行文件后直接运行即可。

Windows 首次运行时，如系统缺少 WebView2 Runtime，程序会提示下载安装。

### 二、使用源码运行

```shell
cd frontend
bun install

cd ../src-tauri
cargo tauri dev
```

更完整的开发说明参见 [开发文档](docs/dev.md)。

## 讨论组

Telegram: [Telegram 讨论组](https://t.me/+mxI34BRClLUwZDcx)

## License

本项目采用 [AGPL-3.0](LICENSE) 许可证。

## Credits

 - ~~[Yuzu](https://github.com/yuzu-emu/yuzu) - Yuzu 模拟器~~
 - [Ryubing/Ryujinx](https://ryujinx.app/) - Ryujinx 模拟器
 - [Eden](https://git.eden-emu.dev/eden-emu/eden) - Eden 模拟器（官方自建 Git 仓库）
 - [Citron](https://citron-neo.github.io/) - Citron 模拟器
 - ~~[hactool](https://github.com/SciresM/hactool) - NS 固件解析~~
 - [nsz](https://github.com/nicoboss/nsz) - NS 固件解析
 - [aria2](https://github.com/aria2/aria2) - aria2 下载器
 - [bytehaul](https://github.com/triwinds/bytehaul) - Rust 异步 HTTP 下载库
 - [Github 镜像源](https://github.com/XIU2/UserScript/blob/master/GithubEnhanced-High-Speed-Download.user.js) - 来自 X.I.U 大佬的 Github 增强脚本
 - [pineappleEA](https://github.com/pineappleEA/pineapple-src) - Yuzu EA 版本来源
 - [THZoria/NX_Firmware](https://github.com/THZoria/NX_Firmware) - NS 固件来源
 - [darthsternie.net](https://darthsternie.net/switch-firmwares/) - NS 固件来源

---

### Overview (`frontend/README.md`)

# Vuetify (Default)

This is the official scaffolding tool for Vuetify, designed to give you a head start in building your new Vuetify application. It sets up a base template with all the necessary configurations and standard directory structure, enabling you to begin development without the hassle of setting up the project from scratch.

## ❗️ Important Links

- 📄 [Docs](https://vuetifyjs.com/)
- 🚨 [Issues](https://issues.vuetifyjs.com/)
- 🏬 [Store](https://store.vuetifyjs.com/)
- 🎮 [Playground](https://play.vuetifyjs.com/)
- 💬 [Discord](https://community.vuetifyjs.com)

## 💿 Install

Set up your project using your preferred package manager. Use the corresponding command to install the dependencies:

| Package Manager                                                | Command        |
|---------------------------------------------------------------|----------------|
| [yarn](https://yarnpkg.com/getting-started)                   | `yarn install` |
| [npm](https://docs.npmjs.com/cli/v7/commands/npm-install)     | `npm install`  |
| [pnpm](https://pnpm.io/installation)                          | `pnpm install` |
| [bun](https://bun.sh/#getting-started)                        | `bun install`  |

After completing the installation, your environment is ready for Vuetify development.

## ✨ Features

- 🖼️ **Optimized Front-End Stack**: Leverage the latest Vue 3 and Vuetify 3 for a modern, reactive UI development experience. [Vue 3](https://v3.vuejs.org/) | [Vuetify 3](https://vuetifyjs.com/en/)
- 🗃️ **State Management**: Integrated with [Pinia](https://pinia.vuejs.org/), the intuitive, modular state management solution for Vue.
- 🚦 **Routing and Layouts**: Utilizes Vue Router for SPA navigation and vite-plugin-vue-layouts for organizing Vue file layouts. [Vue Router](https://router.vuejs.org/) | [vite-plugin-vue-layouts](https://github.com/JohnCampionJr/vite-plugin-vue-layouts)
- 💻 **Enhanced Development Experience**: Benefit from TypeScript's static type checking and the ESLint plugin suite for Vue, ensuring code quality and consistency. [TypeScript](https://www.typescriptlang.org/) | [ESLint Plugin Vue](https://eslint.vuejs.org/)
- ⚡ **Next-Gen Tooling**: Powered by Vite, experience fast cold starts and instant HMR (Hot Module Replacement). [Vite](https://vitejs.dev/)
- 🧩 **Automated Component Importing**: Streamline your workflow with unplugin-vue-components, automatically importing components as you use them. [unplugin-vue-components](https://github.com/antfu/unplugin-vue-components)
- 🛠️ **Strongly-Typed Vue**: Use vue-tsc for type-checking your Vue components, and enjoy a robust development experience. [vue-tsc](https://github.com/johnsoncodehk/volar/tree/master/packages/vue-tsc)

These features are curated to provide a seamless development experience from setup to deployment, ensuring that your Vuetify application is both powerful and maintainable.

## 💡 Usage

This section covers how to start the development server and build your project for production.

### Starting the Development Server

To start the development server with hot-reload, run the following command. The server will be accessible at [http://localhost:3000](http://localhost:3000):

```bash
yarn dev
```

(Repeat for npm, pnpm, and bun with respective commands.)

> Add NODE_OPTIONS='--no-warnings' to suppress the JSON import warnings that happen as part of the Vuetify import mapping. If you are on Node [v21.3.0](https://nodejs.org/en/blog/release/v21.3.0) or higher, you can change this to NODE_OPTIONS='--disable-warning=5401'. If you don't mind the warning, you can remove this from your package.json dev script.

### Building for Production

To build your project for production, use:

```bash
yarn build
```

(Repeat for npm, pnpm, and bun with respective commands.)

Once the build process is completed, your application will be ready for deployment in a production environment.

## 💪 Support Vuetify Development

This project is built with [Vuetify](https://vuetifyjs.com/en/), a UI Library with a comprehensive collection of Vue components. Vuetify is an MIT licensed Open Source project that has been made possible due to the generous contributions by our [sponsors and backers](https://vuetifyjs.com/introduction/sponsors-and-backers/). If you are interested in supporting this project, please consider:

- [Requesting Enterprise Support](https://support.vuetifyjs.com/)
- [Sponsoring John on Github](https://github.com/users/johnleider/sponsorship)
- [Sponsoring Kael on Github](https://github.com/users/kaelwd/sponsorship)
- [Supporting the team on Open Collective](https://opencollective.com/vuetify)
- [Becoming a sponsor on Patreon](https://www.patreon.com/vuetify)
- [Becoming a subscriber on Tidelift](https://tidelift.com/subscription/npm/vuetify)
- [Making a one-time donation with Paypal](https://paypal.me/vuetify)

## 📑 License
[MIT](http://opensource.org/licenses/MIT)

Copyright (c) 2016-present Vuetify, LLC

---

### Overview (`src-tauri/tests/README.md`)

# Eden 集成测试

这是 Eden 模拟器的集成测试套件，用于测试获取版本信息和安装功能。

## 测试概述

### 可用的测试用例

1. **test_get_eden_all_versions** - 获取所有可用的 Eden 版本
2. **test_get_eden_release_info** - 获取指定版本的详细信息
3. **test_get_latest_and_install_eden** - 完整的集成测试：获取最新版本并安装
4. **test_install_specific_eden_version** - 安装指定版本的 Eden
5. **test_performance_get_multiple_releases** - 性能测试：批量获取版本信息

## 运行测试

### 前提条件

1. **网络连接** - 所有测试都需要访问 GitHub API
2. **Aria2** - 下载测试需要 Aria2 支持（安装测试需要）
3. **足够的磁盘空间** - 安装测试会下载实际的安装包（约 50-100MB）

### 运行所有集成测试

由于这些测试需要网络连接和较长时间，默认情况下它们被标记为 `#[ignore]`。

```bash
# 在 src-tauri 目录下
cd src-tauri

# 运行所有被忽略的测试（包括集成测试）
cargo test -- --ignored

# 或者只运行 Eden 集成测试
cargo test --test eden_integration_test -- --ignored

# 显示详细输出（推荐）
cargo test --test eden_integration_test -- --ignored --nocapture
```

### 运行特定测试

```bash
# 只测试获取版本列表（较快）
cargo test test_get_eden_all_versions -- --ignored --nocapture

# 只测试获取版本详情（较快）
cargo test test_get_eden_release_info -- --ignored --nocapture

# 完整安装测试（慢，会下载实际文件）
cargo test test_get_latest_and_install_eden -- --ignored --nocapture

# 性能测试
cargo test test_performance_get_multiple_releases -- --ignored --nocapture
```

### 调整日志级别

测试使用 `tracing` 进行日志输出，可以通过环境变量控制日志级别：

```bash
# 显示详细日志（debug 级别）
RUST_LOG=debug cargo test --test eden_integration_test -- --ignored --nocapture

# 只显示信息日志（默认）
RUST_LOG=info cargo test --test eden_integration_test -- --ignored --nocapture

# 只显示警告和错误
RUST_LOG=warn cargo test --test eden_integration_test -- --ignored --nocapture
```

## 测试说明

### test_get_eden_all_versions

- **用途**: 验证能否成功获取 Eden 的所有可用版本
- **耗时**: 约 1-3 秒
- **网络**: 需要
- **输出**: 版本列表，包含前 5 个版本

### test_get_eden_release_info

- **用途**: 验证能否获取指定版本的详细信息（包括下载链接等）
- **耗时**: 约 1-3 秒
- **网络**: 需要
- **输出**: 版本详情和资源文件列表

### test_get_latest_and_install_eden

- **用途**: 完整的集成测试流程
  1. 获取最新版本
  2. 下载到临时目录
  3. 安装到临时目录
  4. 验证安装结果
- **耗时**: 约 1-5 分钟（取决于网络速度）
- **网络**: 需要
- **磁盘**: 需要临时空间存储下载文件
- **输出**: 详细的安装过程和进度

### test_install_specific_eden_version

- **用途**: 测试安装非最新版本的能力
- **耗时**: 约 1-5 分钟
- **网络**: 需要
- **输出**: 安装过程

### test_performance_get_multiple_releases

- **用途**: 测试批量获取版本信息的性能
- **耗时**: 约 5-10 秒
- **网络**: 需要
- **输出**: 性能统计信息

## 注意事项

1. **临时文件**: 所有测试都使用临时目录，测试结束后会自动清理
2. **配置隔离**: 测试使用独立的配置，不会影响主程序的配置文件
3. **网络容错**: 如果网络失败，测试会记录警告而不是直接失败
4. **Aria2 依赖**: 下载测试需要系统中安装了 Aria2

## 故障排查

### 测试失败：无法连接到 GitHub

- 检查网络连接
- 检查是否需要配置代理
- GitHub API 可能有速率限制

### 测试失败：Aria2 错误

- 确认 Aria2 已安装并在 PATH 中
- 检查 Aria2 配置

### 测试超时

- 网络速度较慢时可能需要更长时间
- 考虑只运行轻量级测试（如版本获取测试）

## 示例输出

```
running 1 test
test test_get_latest_and_install_eden ... ok
开始测试：获取最新版本并安装 Eden
步骤 1: 获取最新版本
最新版本: v1.0.0
步骤 2: 创建临时安装目录
临时目录: C:\Users\...\Temp\...
步骤 3: 开始下载并安装 Eden v1.0.0
Eden 下载 15.2% (8/52 MB) @ 1024 KB/s
Eden 下载 35.8% (18/52 MB) @ 2048 KB/s
Eden 下载 58.4% (30/52 MB) @ 2048 KB/s
Eden 下载 81.7% (42/52 MB) @ 2048 KB/s
Eden 下载 99.9% (52/52 MB) @ 2048 KB/s
步骤 4: 验证安装结果
Eden 安装路径: C:\Users\...\Temp\...\emulator\eden.exe
测试完成: Eden v1.0.0 安装成功

test result: ok. 1 passed; 0 failed; 0 ignored; 0 measured; 4 filtered out
```

---

### Overview (`frontend/src/components/README.md`)

# Components

Vue template files in this folder are automatically imported.

## 🚀 Usage

Importing is handled by [unplugin-vue-components](https://github.com/unplugin/unplugin-vue-components). This plugin automatically imports `.vue` files created in the `src/components` directory, and registers them as global components. This means that you can use any component in your application without having to manually import it.

The following example assumes a component located at `src/components/MyComponent.vue`:

```vue
<template>
  <div>
    <MyComponent />
  </div>
</template>

<script lang="ts" setup>
  //
</script>
```

When your template is rendered, the component's import will automatically be inlined, which renders to this:

```vue
<template>
  <div>
    <MyComponent />
  </div>
</template>

<script lang="ts" setup>
  import MyComponent from '@/components/MyComponent.vue'
</script>
```

---

### Overview (`frontend/src/layouts/README.md`)

# Layouts

Layouts are reusable components that wrap around pages. They are used to provide a consistent look and feel across multiple pages.

Full documentation for this feature can be found in the Official [vite-plugin-vue-layouts](https://github.com/JohnCampionJr/vite-plugin-vue-layouts) repository.

---

### Overview (`frontend/src/plugins/README.md`)

# Plugins

Plugins are a way to extend the functionality of your Vue application. Use this folder for registering plugins that you want to use globally.

---

### Overview (`frontend/src/stores/README.md`)

# Store

Pinia stores are used to store reactive state and expose actions to mutate it.

Full documentation for this feature can be found in the Official [Pinia](https://pinia.esm.dev/) repository.

---

### Overview (`frontend/src/styles/README.md`)

# Styles

This directory is for configuring the styles of the application.

---

### Dev (`docs/dev.md`)

# Dev

## 当前技术栈

项目现在已经从旧的 Python/Eel 方案切换到 **Rust + Tauri 2**：

- 桌面端后端：Rust（`src-tauri`）
- 前端：Vue 3 + Vite + Vuetify（`frontend`）
- 前端构建产物：`web`

本文档中的开发流程以当前的 Rust/Tauri 架构为准，旧的 Python 启动方式已经不再适用。

## 开发环境需求

- Rust stable 工具链（`rust-version = 1.70` 及以上）
- Tauri CLI
- Bun
- Node.js 20+

如果你在 Windows 上开发，通常还需要：

- Visual Studio C++ Build Tools（MSVC）
- WebView2 Runtime

## 环境准备

### Step 1 安装前端依赖

```shell
cd frontend
bun install
```

### Step 2 安装 Tauri CLI

如果本机还没有安装 Tauri CLI，可以执行：

```shell
cargo install tauri-cli
```

### Step 3 确认 Rust 工具链

```shell
rustup show
cargo --version
```

## 本地运行

在 `src-tauri` 目录启动 Tauri 开发模式：

```shell
cd src-tauri
cargo tauri dev
```

说明：

- `cargo tauri dev` 会读取 `src-tauri/tauri.conf.json`
- 会自动执行前端 dev server（`bun run --cwd ../frontend dev`）
- 前端默认运行在 `http://localhost:3000`

## 前端单独调试

如果只想调试页面样式或交互，可以单独启动 Vite：

```shell
cd frontend
bun dev
```

需要注意，这种方式只会启动前端页面；如果页面依赖 Tauri 的 Rust 命令，仍然建议通过 `cargo tauri dev` 联调。

## 构建

### 仅构建前端资源

```shell
cd frontend
bun build
```

构建结果会输出到项目根目录下的 `web`。

### 构建桌面应用

```shell
cd src-tauri
cargo tauri build
```

说明：

- `cargo tauri build` 会自动调用前端构建命令
- 最终产物由 Tauri 按平台进行打包

## Rust 开发与检查

Rust 代码主要位于：

- `src-tauri/src/commands`：Tauri 命令入口
- `src-tauri/src/services`：核心业务逻辑
- `src-tauri/src/repositories`：数据访问与平台适配
- `src-tauri/src/models`：数据模型

日常开发建议至少执行：

```shell
cd src-tauri
cargo fmt
cargo check
```

如需运行测试：

```shell
cd src-tauri
cargo test
```

## 调试建议

- 调试前后端联动时，优先使用 `cargo tauri dev`
- 调试 Rust 逻辑时，可直接使用支持 Rust 的 IDE（如 RustRover、VS Code + rust-analyzer）
- 修改前端后如需验证最终构建结果，可先执行 `bun build`，再执行 `cargo tauri build`

## 说明

以下旧流程已经废弃，不再适用于当前项目：

- `poetry run python main.py`
- `uv run python ui.py`
- `uv sync`
- 基于 Eel/gevent 的 Python 调试方式

---

### Plan Citron Stable Nightly Branches Plan (`docs/plan/citron-stable-nightly-branches-plan.md`)

# Citron Stable/Nightly 分支拆分计划

## 背景

当前 Yuzu 页面把 Citron Neo 作为单一分支 `citron` 展示和处理，而 Citron Neo 模拟器自身的更新检查已经把 Stable 与 Nightly 作为两个渠道：

- Stable release 源：`https://api.github.com/repos/citron-neo/emulator/releases`
- Nightly release 源：`https://api.github.com/repos/citron-neo/CI/releases`

本计划目标是把现有下拉列表里的 “Citron” 拆成 “Citron Stable” 与 “Citron Nightly” 两项，交互方式参考 Ryujinx 的 Mainline/Canary 分支。

## 目标

- 前端 Yuzu 页面下拉列表展示独立的 `Citron Stable` 与 `Citron Nightly`。
- 后端分支参数支持稳定的内部值，例如 `citron-stable` 与 `citron-nightly`。
- 旧配置中的 `citron` 保持兼容，默认迁移或等价映射到 `citron-stable`。
- 获取版本、安装、变更日志、检测当前安装版本和分支时，都能正确区分两个 Citron 渠道。
- 现有 Eden 行为不受影响。

## 设计

### 分支命名

新增 Yuzu 分支值：

- `citron-stable`：对应 Citron Neo Stable。
- `citron-nightly`：对应 Citron Neo Nightly。

兼容旧值：

- `citron` 继续被后端接受，按 `citron-stable` 处理。
- 配置加载或分支切换时可逐步把 `citron` 写回为 `citron-stable`，避免旧用户下拉框无选中项。

### Release 数据源

在 `src-tauri/src/repositories/yuzu.rs` 中拆分 Citron release API：

- Stable 使用 GitHub Releases API，走 `request_github_api` 和 `ReleaseInfo::from_github_api`。
- Nightly 使用 GitHub Releases API，走 `request_github_api` 和 `ReleaseInfo::from_github_api`。
- Nightly 的版本号不使用平台 tag（例如 `nightly-windows`），而是从 `body` / `name` / 资产名中提取 `Citron Upstream Commit` 的短 SHA，例如 `fab192f`。同一个 upstream SHA 下的 Windows、macOS、Linux release 资产需要合并成同一个版本条目，安装时再按当前平台筛选资产。
- 上游 Citron Neo updater 源码曾出现 `https://git.citron-neo.org/api/v1/repos/Citron/Emulator/releases` 这种 Forgejo/Gitea 风格 API，但当前环境无法解析该域名；本工具应优先使用当前可访问且现有代码已在使用的 GitHub API。

需要更新的入口：

- `get_all_yuzu_release_versions(branch)`
- `get_yuzu_all_release_info(branch)`
- `get_yuzu_release_info_by_version(version, branch)`
- `get_latest_change_log(branch)`
- unsupported branch 错误文案和测试

### 安装与资源选择

在 `src-tauri/src/services/yuzu.rs` 中统一分支判断：

- 所有 Citron 变体共用安装路径、可执行文件名、用户目录识别和 macOS bundle 校验逻辑。
- 资源选择不应依赖资产名中的 `stable` 或 `nightly` 文本来判断渠道。当前 `citron-neo/emulator` 的 tagged release 源虽然作为 Stable 使用，但桌面资产名仍可能是 `Citron-windows-nightly-...`、`Citron-macOS-nightly-...`、`citron_nightly-...AppImage`。
- Stable/Nightly 渠道由用户选择的分支值和对应 release API 决定；资产名只用于筛选平台、架构、包格式和工具链。
- Windows 继续优先选择非 PGO 的 `.zip`，并沿用现有 Citron 偏好 `x64-msvc`、再回退 `x64-clangtron` 的策略。
- macOS 继续选择 `.dmg`，并排除 `.zsync` 等增量更新文件。
- Linux 当前仍按既有支持策略处理 AppImage，不把文件名中的 `nightly` 当作渠道判断条件。
- 如果当前逻辑只判断 `branch == "citron"`，改成辅助函数，例如 `is_citron_branch(branch)`。
- 安装完成写入配置时保存具体分支值，优先保存用户选择的 `citron-stable` 或 `citron-nightly`。

### 版本和分支检测

当前检测逻辑已经能从窗口标题、版本字符串或可执行文件元数据识别 Citron。需要补齐：

- 检测到 Citron 但无法确定渠道时，默认返回 `citron-stable`，与旧 `citron` 兼容语义保持一致。
- 不应仅凭安装包或资产名包含 `nightly` 就判定为 `citron-nightly`，因为 Stable 源的 tagged release 资产名也可能带 `nightly`。
- 如果版本文件、配置或明确元数据能证明来自 Stable 源，返回 `citron-stable`。
- 如果明确来自 CI/nightly 源，或 release/tag 元数据指向 `citron-neo/CI`，返回 `citron-nightly`。
- 对本地已安装 Citron 但无法可靠判断渠道的情况，默认返回 `citron-stable`。
- 旧的 `citron` 检测结果在写入配置前规范化为 `citron-stable`。

### 前端

在 `frontend/src/pages/yuzu.vue` 中更新 `branches`：

- `Eden`
- `Citron Stable`
- `Citron Nightly`
- 已关闭的 Yuzu 主线/EA 保持原状

`branchMap`、`selectedEmulatorName`、版本加载、安装和切换逻辑继续使用分支 value 传给 Tauri。初始化时如果配置里读到旧值 `citron`，前端也应显示为 `citron-stable`，避免空选中。

相关类型和默认配置可同步检查：

- `frontend/src/types/index.ts`
- `frontend/src/types/DefaultConfig.ts`
- `frontend/src/utils/tauri.ts`

## 实施步骤

1. 增加 Rust 侧分支常量和规范化函数，例如 `normalize_yuzu_branch`、`is_citron_branch`、`is_citron_stable_branch`、`is_citron_nightly_branch`。
2. 拆分 `repositories/yuzu.rs` 中 Citron Stable/Nightly 的 release API 与解析函数。
3. 调整 `services/yuzu.rs` 中所有 Citron 分支判断，让安装、资源筛选、检测和配置写入使用规范化分支。
4. 调整 `commands/yuzu.rs`，确保 `switch_yuzu_branch`、安装和版本查询都接受新分支值。
5. 更新 `frontend/src/pages/yuzu.vue` 下拉列表和旧 `citron` 映射。
6. 增加或更新 Rust 单元测试，覆盖分支规范化、release 解析、资产选择和旧 `citron` 兼容。
7. 如前端有测试或类型检查脚本，补跑对应校验。

## 验证

修改 Rust 后按仓库要求执行：

- `cargo fmt`
- `cargo check`
- Windows target 的 `cargo check`
- 如果从 Windows 验证 macOS target，使用 `cargo zigbuild`

功能验证项：

- Yuzu 页面下拉框能看到 `Citron Stable` 与 `Citron Nightly`。
- 两个 Citron 分支分别加载不同 release 源的版本列表。
- `citron-nightly` 版本列表显示 upstream 短 SHA，例如 `fab192f`，而不是 `nightly-windows` 这类平台 tag。
- 选择任一 Citron 分支后安装时下载所选 release 源中的平台匹配资产，即使 Stable 源资产名包含 `nightly` 也不应被排除。
- 旧配置 `branch: "citron"` 打开后仍可正常加载，并落到 Stable 兼容路径。
- Eden 安装和版本列表不受影响。

纯后端端到端验证项：

- 为 `citron-stable` 和 `citron-nightly` 各跑一次版本列表获取，确认返回非空列表，且请求源分别是 `citron-neo/emulator` 与 `citron-neo/CI`。
- 确认 `citron-nightly` 返回的版本值是 7 位 upstream 短 SHA，并且用该 SHA 继续调用 release 详情能反查到对应 release 与资产。
- 对两个分支各取最新版本调用 release 详情接口，确认能解析 release 元数据和资产列表。
- 对两个分支各跑一次下载 URL 解析或安装前校验流程，确认能选出当前平台可用资产；Stable 源资产名包含 `nightly` 时也必须通过。
- 通过 Tauri command 层或 Rust 集成测试调用 `get_all_yuzu_versions` / `install_yuzu_by_version` 的后端路径，覆盖从分支参数进入到 repository/service 的完整链路。
- 如果真实安装会写入本机模拟器目录，端到端测试应使用临时目录或只验证到下载 URL 选择阶段，避免污染用户现有安装。

## 风险

- Stable 与 Nightly 都是 GitHub Releases API，字段形态一致，核心字段为 `tag_name`、`name`、`body`、`published_at`、`assets[].name`、`assets[].browser_download_url`。风险不在 JSON schema，而在两个仓库的发布策略和资产命名是否持续稳定。
- Nightly 的可选版本依赖 `Citron Upstream Commit` 或资产名中的 upstream SHA；如果 CI release 文案或资产命名规则变化，可能需要更新 SHA 提取逻辑。
- 上游源码里保留过 `git.citron-neo.org/api/v1/...` 的 Stable URL，但该域名当前不可解析；不要把它作为本工具的默认 Stable 源，除非后续确认官方恢复该域名。
- Stable 源资产名目前也带 `nightly`，因此资产名不能作为渠道判定依据；只能作为平台、架构、格式和工具链筛选依据。
- 旧用户配置、历史路径和检测结果如果仍写入 `citron`，前端可能出现下拉框选中状态不一致，需要统一规范化。

---

--- METRICS ---
- Files Extracted: 10
- Estimated Token Budget: ~4790 tokens
- Canonical Reference: https://codewiki.google/github.com/triwinds/ns-emu-tools
