# BlueArchiveToolkit 用户指南 本指南面向 `bat` 官方资源同步二进制的使用者,覆盖:命令、选项、退出码、运行时行为,以及统一错误码参考。 - 权威运行/部署说明另见 `docs/guides/official-resource-test-pull.md` 和 `docs/guides/deployment.md`。 - 本文档中的命令、选项以 `bat --help` 为准;错误码以 `core/src/error_code.rs` 的码表为准。 --- ## 1. 概览 `bat` 是 Linux 上官方日服(Yostar JP)资源同步的正式入口。它可以: - `--auto-discover` 从官方 HTTP metadata 解析 `GameMainConfig`,自动获得 app-version、连接组和 server-info,不安装、不启动官方启动器;已发布 release 会保存 `official-launcher-bootstrap.json`。 - 生成官方全量 pull plan、执行真实下载,维护 release 内的下载 manifest,并做 size + BLAKE3 复用校验、官方 seed `.hash`(标准 xxHash32(seed=0))强校验、ZIP 结构校验。 - 断点续传、失败分类重试、下载 quarantine、本地 manifest audit/repair。 - 原子发布:先写 `.staging/`,校验通过后发布 `versions/` 并原子切换 `current` symlink。 - 常驻运行(`--watch`)或后台化(`--daemon`),通过 `bat.sock` Unix socket JSON-RPC 控制。 ### 运行形态 ```bash # 一次性 dry-run(不写状态) bat --auto-discover --dry-run # 前台常驻 bat --auto-discover --watch --output /var/lib/bluearchive-toolkit/official # 后台守护 bat --auto-discover --daemon --output /var/lib/bluearchive-toolkit/official ``` 带凭据的代理**推荐用环境变量**(凭据不进命令行/argv/状态文件): ```bash HTTPS_PROXY=http://user:pass@127.0.0.1:7890 bat --auto-discover --daemon ``` --- ## 2. 命令 无子命令时执行一次性同步(或配合 `--watch`/`--daemon`)。子命令如下: | 命令 | 说明 | |---|---| | `res pull` | 拉取官方资源;支持单次、限定次数和 `--watch` 周期执行 | | `res schedule` | 管理资源拉取计划;CLI、RPC 和 `bat-api` dashboard 共用计划状态 | | `parse run` | 执行当前官方 release 的解析和 TextUnit 队列刷新 | | `parse clear-cache` | 使用 `--force` 清理当前 release 的可再生解析缓存和翻译队列 | | `parse repack` | 根据 JSON spec 批量重打包 UnityFS bundle | | `parse schedule` | 管理解析计划;与 `res schedule` / `i18n schedule` 共用同一计划状态 | | `i18n run` / `i18n export` | 刷新离线翻译队列或导出可编辑翻译工作台 | | `i18n set` / `i18n get` / `i18n unset` | 手动查看、修改或清空一个翻译工作台条目;也可通过 `i18n workbench ...` 或 `--workbench` 访问 | | `i18n validate` | 发布前校验工作台 release、source text 和 patch 目标 | | `i18n proofread` | 将当前汉化 workflow 标记为人工校对中 | | `i18n tasks` / `i18n task list` / `i18n task status` | 查询当前离线 TextUnit 翻译任务状态 | | `i18n handoff` | 查询当前翻译交接视图 | | `i18n status` | 显示当前汉化 release 状态 | | `i18n task update` | 回写 provider worker 任务状态 | | `i18n worker run` | 运行真实 provider worker;支持单次、限定次数和周期执行 | | `i18n publish` | 校验工作台并发布独立汉化 release;`--force` 使用新的手动 release ID | | `i18n schedule` | 管理翻译和汉化发布计划 | | `refresh` | 执行一次更新检查;若有 live daemon,则通过 RPC 请求其刷新 | | `verify` | 校验远端计划、本地 manifest 和官方 seed hash(dry-run + 审计当前 release) | | `repair` | 重新下载本地校验失败的资源 | | `status` | 显示 daemon 状态 | | `stop` | 停止 daemon | | `restart` | 重启 daemon;未显式传参时复用保存的参数 | | `reload` | 请求 daemon 重新自动发现并强制刷新 | | `logs` | 显示 daemon 日志尾部(配合 `--tail`) | | `doctor` | 运行时诊断(输出目录、状态目录、curl/unzip、代理、PID、socket、锁) | | `clean-stable` | 清理 `.part`/`.tmp`/失效锁、PID、socket(daemon 运行中会拒绝执行) | `status`/`stop`/`logs`/`reload` 和默认形态的 `refresh` 优先走 `bat.sock` JSON-RPC;socket 不可用时 `status`/`stop` 回退到 PID/状态文件兼容路径。 Rust `bat` 工作流的完整命令、工作台字段、重打包 spec、调度计划和 `bat-api` 调度接口见 [`docs/guides/bat-workflows.md`](docs/guides/bat-workflows.md)。 一级命令推荐使用短名称 `res`、`parse`、`i18n`;`resource`、`resources`、 `translation`、`translate` 仍是兼容别名。 其中 `translation` / `translate` 也支持 `tasks`、`handoff`、`status` 和 `task update`;`--translation-file` 也可写成 `--workbench`,`--schedule-id` / `--schedule-action` 也可简写为 `--id` / `--action`。 `resource status`、`resource schedule`、`translation tasks`、`translation handoff` 和 `translation status` 也都与对应短命令一致。 ### bat-api 资源 bootstrap / 分发服务 `bat-api` 是 Go 侧正式服务入口,用于给客户端、补丁器或上层工具提供启动前资源入口和 CDN 形态只读分发。它不负责自动发现、下载、校验或发布资源;这些长期状态由 Rust `bat` / daemon 持有。 生产拓扑上,`bat-api` 基本应与 Rust `bat` 运行在同一台服务器、同一容器或同一共享文件系统环境。当前可读资源目录不在 `bat-api` 配置里写死,而是由 `bat.sock` RPC 的 `catalog.status` / `resource.manifest` 返回 `resource_root`。 推荐运行关系: ```bash # 先让 Rust bat 生产并维护 release bat --auto-discover --daemon \ --output /var/lib/bluearchive-toolkit/official \ --state-dir /var/lib/bluearchive-toolkit/daemon-state # 再启动 bat-api 读取同一个 daemon socket bat-api \ --listen :18080 \ --public-base-url http://127.0.0.1:18080 \ --socket /var/lib/bluearchive-toolkit/daemon-state/bat.sock \ --refresh-interval 1m ``` 测试、fixture 或应急只读诊断场景可用 `--resource-root ` 直接指向已发布 release 根;生产默认应通过 `--socket` / `BAT_API_SOCKET` 从 `bat.sock` 发现当前版本。`bat.sock` 不应暴露到公网;对外发布时只暴露 `bat-api` HTTP,并把 `--public-base-url` 设为客户端实际访问的 HTTPS 根。 开发环境不能本地全量运行 `bat` 时,用 fixture 验证 Go 服务面即可: ```bash BAT_API_SKIP_ENV_FILE=1 go run ./cmd/bat-api \ --listen 127.0.0.1:18080 \ --public-base-url http://127.0.0.1:18080 \ --resource-root internal/api/testdata/release \ --refresh-interval 0 ``` 常用接口: | 接口 | 说明 | |---|---| | `GET /healthz` | 服务存活、RPC 可用性、release ready 状态和最近一次 RPC refresh 诊断 | | `GET/HEAD /readyz` | release 就绪检查;当前无可分发 release 时返回 `503` | | `GET /v1/bootstrap` | 启动前资源入口:`bat` RPC 健康、release 摘要、server-info URL、client-patch base、改写后的 Addressables root | | `GET /v1/launcher/bootstrap` | 启动器资源引导聚合视图:release、launcher metadata、GameMainConfig 摘要和资源 URL | | `GET /api/launcher/game/config` | launcher 资源 metadata 兼容 envelope;字段来自 Rust `bat` 已发布 snapshot/RPC | | `GET /api/launcher/game/config/json` | launcher 形状的资源引导 JSON URL;不会返回完整 PC package update manifest | | `GET /api/launcher/advanced/game/download/cdn` | launcher 形状的 CDN 配置;返回当前 `--public-base-url`,用于资源引导 | | `GET /api-launcher-jp.yo-star.com/api/launcher/...` | 与上面 `/api/launcher/...` 等价,便于反代或 hosts 映射保持官方 host 形状 | | `GET /v1/release` | 当前 release 摘要 | | `GET /v1/resources?offset=0&limit=100` | 当前 manifest 索引分页 | | `GET /v1/server-info` | 调试用 server-info JSON,只改 `AddressablesCatalogUrlRoot` | | `GET /yostar-serverinfo.bluearchiveyostar.com/server-info.json` | 官方 host/path 形态的 server-info | | `GET/HEAD /prod-clientpatch.bluearchiveyostar.com/...` | 官方 CDN path 形态资源字节 | | `GET /openapi.yaml` | bat-api OpenAPI 文档 | | `GET /admin/` | 管理控制入口与允许操作列表 | | `GET /admin/dashboard/` | 内嵌管理 dashboard 静态页面;页面调用的管理 API 仍需要 token | | `GET /admin/diagnostics` | 读取 Rust daemon 诊断;需要管理 token | | `GET /admin/logs?tail=200` | 读取 Rust daemon 日志尾部;需要管理 token | | `GET /admin/tasks` | 读取 Rust daemon 任务列表;需要管理 token | | `GET /admin/tasks/status?task_id=...` | 读取单项任务状态;需要管理 token | | `GET /admin/tasks/logs?task_id=...` | 读取单项任务日志;需要管理 token | | `GET /admin/schedules?id=...&group=...&enabled=...` | 读取/过滤 Rust `bat` 调度计划;需要管理 token | | `GET /admin/parse/status` | 读取当前 release 解析状态;需要管理 token | | `GET /admin/parse/text-units?...` | 分页查询当前 release TextUnit 明细;需要管理 token | | `GET /admin/parse/errors?...` | 分页查询当前 release 解析错误;需要管理 token | | `GET /admin/translation/tasks?limit=100&worker_status=failed` | 读取/过滤 Rust 翻译任务和 provider worker 状态;需要管理 token | | `GET /admin/translation/handoff` | 读取当前 release 的完整翻译交接视图;需要管理 token | | `GET /admin/translation/status` | 读取当前汉化 release、current 指针和 workflow 状态;需要管理 token | | `POST /admin/control/{action}` | 经白名单转发 Rust `bat` 控制请求;见下文 | launcher 兼容端点只服务启动前资源发现。它们复用 Rust `bat` snapshot 中的 `launcher_metadata` 和 `game_main_config_bootstrap`,显式标记 `scope=resource_bootstrap_only` / `package_update_manifest=false`。`bat-api` 不下载 launcher 包,不生成官方 PC package update manifest,也不仿造登录、账号、网关、鉴权或游戏业务协议。 生产面对玩家分发时,应启用 HTTP token 鉴权、限流和访问日志: - `BAT_API_AUTH_TOKEN`:启用 `Authorization: Bearer `、`X-BAT-Token` 或 query fallback 鉴权;token 推荐由 secret manager 或进程环境提供,不建议写入提交文件。`/admin/control/*`、`/admin/schedules`、`/admin/tasks*`、`/admin/logs`、`/admin/diagnostics`、`/admin/parse/*` 和 `/admin/translation/*` 需要此 token;`/admin/dashboard/` 静态资产默认免鉴权,便于浏览器打开后再在页面内配置 token。 - `BAT_API_AUTH_QUERY_PARAM`:query fallback 参数名,默认 `bat_token`;兼容不能写 header 的客户端,访问日志不会记录 query。 - `BAT_API_AUTH_EXEMPT_PATHS`:逗号分隔的免鉴权 path 或 slash-prefix,例如 `/healthz,/readyz`。 - `BAT_API_RATE_LIMIT_RPS` / `BAT_API_RATE_LIMIT_BURST`:按客户端 IP 的进程内 token bucket 限流;边缘反代/CDN 仍应配置独立限流。 - `BAT_API_TRUST_PROXY_HEADERS`:只有反代已经清洗并覆盖 `X-Forwarded-For` / `X-Real-IP` 时才设为 `true`。 - `BAT_API_ACCESS_LOG`:结构化访问日志,记录 method/path/status/bytes/duration/client_ip/request_id/user_agent,不记录 query string。 - `BAT_API_MAX_RESOURCE_LIMIT`:`/v1/resources` 最大分页上限,默认 `1000`。 `POST /admin/control/{action}` 只转发固定白名单内的 Rust RPC,不是任意 RPC proxy: | action | Rust RPC | 参数 | 返回 | |---|---|---|---| | `reload` | `daemon.reload` | 无 | `202` accepted | | `refresh` | `daemon.refresh` | 可选 `{ "force": true }` | `202` accepted | | `restart` | `daemon.restart` | 无 | `202` accepted | | `sync` | `resource.sync` | 可选 `{ "force": true }` | `202` + task | | `verify` | `resource.verify` | 无 | `202` + task | | `repair` | `resource.repair` | 无 | `202` + task | | `catalog-refresh` | `catalog.refresh` | 可选 `{ "force": true }` | `202` + task | | `schedule-add` | `schedule.add` | 调度 mutation JSON | `202` + Rust schedule report | | `schedule-update` | `schedule.update` | 调度 mutation JSON | `202` + Rust schedule report | | `schedule-remove` | `schedule.remove` | `{ "id": "..." }` | `202` + Rust schedule report | | `schedule-run` | `schedule.run` | 可选 `{ "id": "...", "force": true }` | `202` + 执行报告 | | `task-cancel` | `task.cancel` | `{ "task_id": "..." }` | `202` + 取消请求结果 | | `translation-task-update` | `translation.task.update` | `{ "task_id": "...", "status": "completed", "provider": "manual", "provider_run_id": "...", "translation_results": [{ "unit_id": "...", "source_text": "...", "translated_text": "..." }] }` | `202` + 当前任务记录 | | `translation-worker-run` | `translation.worker.run` | `{ "provider": "mock", "concurrency": 8, "max_tasks": 2 }` | `202` + worker task | | `translation-proofread` | `translation.proofread` | 无 | `202` + 汉化状态 | | `localized-publish` | `localized.publish` | `{ "translation_file": "...", "localized_release_id": "..." }` 或 `{ "from_worker": true, "localized_release_id": "..." }` | `202` + localized release manifest | | `localized-rollback` | `localized.rollback` | 可选 `{ "localized_release_id": "..." }` | `202` + rollback report | `stop`、`clean-stable`、patch 和 UnityFS 写入命令不会经 HTTP 暴露。 所有动态 JSON(bootstrap、health、ready、release、resources、launcher 兼容、server-info、OpenAPI、admin 和错误响应)显式返回 `Cache-Control: no-store`。资源字节 CDN path 仍返回长期 immutable cache header。 CDN path 只服务 manifest 索引内且磁盘存在、size 匹配的文件。响应支持 `GET`、`HEAD`、`Range`、条件请求、ETag、Last-Modified、Accept-Ranges 和长期缓存头;ETag 优先使用 manifest 中的 BLAKE3。`.hash` 以 `text/plain` 返回,其它未知扩展默认为 `application/octet-stream`。 `bat-api` 只改写资源相关入口:server-info 中的 `AddressablesCatalogUrlRoot` 会指向 `--public-base-url` 下的 `prod-clientpatch...` path;`ApiUrl`、`GatewayUrl`、登录、账号、网关和游戏业务协议不会被仿造或改写。 示例: ```bash curl -fsS http://127.0.0.1:18080/v1/bootstrap curl -fsS http://127.0.0.1:18080/v1/launcher/bootstrap curl -fsS http://127.0.0.1:18080/api-launcher-jp.yo-star.com/api/launcher/game/config curl -fsS http://127.0.0.1:18080/openapi.yaml curl -fsS \ http://127.0.0.1:18080/prod-clientpatch.bluearchiveyostar.com//TableBundles/TableCatalog.hash curl -i -H 'Range: bytes=0-1023' \ http://127.0.0.1:18080/prod-clientpatch.bluearchiveyostar.com//TableBundles/TableCatalog.bytes ``` --- ## 3. 选项 ### 发现(Discovery) | 选项 | 说明 | |---|---| | `--auto-discover` | 自动发现 app-version、server-info、连接组 | | `--server-info-url ` | 使用官方 server-info URL | | `--server-info-file ` | 使用官方 server-info 文件名 | | `--server-info-path ` | 使用本地 server-info JSON 文件 | | `--app-version ` | 覆盖 app 版本 | | `--connection-group ` | 覆盖连接组 | | `--launcher-version ` | 启动器 metadata API 版本(默认 `1.7.2`) | ### 同步(Sync) | 选项 | 说明 | |---|---| | `--platforms ` | 平台,如 `Windows,Android`(默认 `Windows,Android`) | | `--output ` | 资源发布根目录(默认 `./bat-resources`) | | `--snapshot ` | 覆盖 snapshot 路径(默认 `/current/official-sync-snapshot.json`) | | `--curl ` | curl 可执行文件(默认 `curl`) | | `--proxy ` | curl 代理覆盖(默认 `auto`,从环境变量检测)。scheme 支持 http/https/socks4/socks4a/socks5/socks5h | | `--no-proxy` | 强制直连 | | `--unzip ` | unzip 可执行文件(默认 `unzip`) | | `--dry-run` | 不写同步状态 | | `--plan` | dry-run 时输出计划中的 URL | | `--force` | 强制下载/刷新 | | `--audit-local` / `--no-audit-local` | 启用/关闭本地 manifest 审计 | | `--repair` / `--no-repair` | 启用/关闭自动修复 | ### 守护(Daemon) | 选项 | 说明 | |---|---| | `--watch` | 前台常驻循环 | | `--daemon` | 启动脱离终端的后台 watch 进程 | | `--state-dir ` | 后台状态目录(默认 `/tmp/bat-pid`) | | `--interval ` | 正常检查周期(默认 `1h`) | | `--error-retry ` | 失败后重试周期(默认 `60s`) | | `--quiet-up-to-date` / `--no-quiet-up-to-date` | 静默/总是打印 up-to-date 报告 | | `--tail ` | `logs` 命令返回的日志行数(默认 `200`) | ### 输出(Output) | 选项 | 说明 | |---|---| | `--human` | 人类可读输出(默认) | | `--json` | 面向脚本的稳定 JSON 输出 | | `--progress` / `--no-progress` | 启用/关闭 stderr 进度日志 | | `--banner` / `--no-banner` | 启用/关闭启动横幅 | | `-h`, `--help` | 显示帮助 | ### 默认值与运行时行为 - 平台:`Windows,Android`。 - 资源输出:`./bat-resources`(`current` → `versions/`、`.staging/`;自动发现 release 下包含 `official-launcher-bootstrap.json`,维护期 pending 证据位于发布根 `official-launcher-bootstrap.pending.json`)。 - 后台状态目录:`/tmp/bat-pid`(`bat.sock`、`bat.pid`、`bat-status.json`、`bat-daemon.log`、`bat-events.jsonl`、任务历史 `bat-tasks.json`、短生命周期 `bat-control.lock`;代理凭据在 `bat-proxy.secret`,`0600`)。 - 强制刷新:每天北京时间(UTC+8)`03:00`、`16:00`、`18:00` 各一次。 - 状态类文件默认 `0600` 权限,读写不跟随 symlink。 ### 配置文件(`.env`,无参启动) `bat` 首次启动时会在**二进制所在目录**释放一个 `.env` 配置模板(`0600` 权限,已存在则不动)。之后每次启动自动加载该文件,把其中的键作为进程环境变量(不覆盖已存在的环境变量),因此编辑 `.env` 后直接运行 `bat`(无参数)即可按配置启动。 - 优先级:**命令行参数 > 进程环境变量 > `.env` > 内置默认值**。 - 语法:每行 `KEY=VALUE`;`#` 开头为注释;值两侧成对引号会剥除;空值视为未设置。 - 支持的键:`BAT_OUTPUT`、`BAT_STATE_DIR`、`BAT_AUTO_DISCOVER`、`BAT_WATCH`、`BAT_DAEMON`、`BAT_PROXY`、`BAT_NO_PROXY`、`BAT_INTERVAL_SECONDS`、`BAT_ERROR_RETRY_SECONDS`、`BAT_APP_VERSION`、`BAT_CONNECTION_GROUP`、`BAT_LAUNCHER_VERSION`、`BAT_PLATFORMS`、`BAT_CURL`、`BAT_UNZIP`、`BAT_JSON`、`BAT_QUIET_UP_TO_DATE`;也可以直接写 `HTTPS_PROXY` 等通用环境变量(走现有代理自动检测)。布尔值支持 `1/0/true/false/yes/no/on/off`。 - `BAT_WATCH` / `BAT_DAEMON` 只对无子命令的 `bat` 生效(两者同时为 `1` 时 daemon 优先);命令行显式传入 `--watch` / `--daemon` / `--dry-run` 时 `.env` 的模式开关让位。`status` / `verify` 等子命令不受它们影响。 - `BAT_REDIS_URL` / `BAT_REDIS_PASSWORD` 为**预留键**:Redis 任务后端尚未接入,当前任务历史持久化在 `/bat-tasks.json`。 - 设 `BAT_SKIP_ENV_FILE=1` 可让 `bat` 完全跳过 `.env` 的生成与加载。 --- ## 4. 退出码 | 退出码 | 含义 | |---|---| | `0` | 成功;`verify`/`doctor` 检查通过 | | `1` | 普通错误 | | `75` | 资源目录锁冲突(有 live daemon 正在管理同一目录,或 `.official-sync.lock` 被占用) | `verify` 或 `doctor` 发现问题也返回非 0。`--json` 模式下错误以 JSON 写到 stderr。 --- ## 5. 错误码参考 `bat` 使用一套稳定的数字错误码,作为 CLI、daemon RPC 和结构化日志的公共错误契约。 - **格式**:`BAT-ERR-<域 3 位><序号 3 位>`,共 6 位,例如 `BAT-ERR-300012`。 - **域**:错误码首位按百位分大类。 - **承载结构**(RPC envelope 的 `error` 字段、`--json` 输出、`bat-events.jsonl` 一致): ```json "error": { "code": "BAT-ERR-310001", "kind": "proxy_failure", "domain": "network", "location": "official-sync.download.pull_one", "message": "代理返回 407 认证失败", "retryable": false } ``` `location` 是稳定的「组件·操作」标签(跟随语义、不随行号漂移)。`retryable` 是该类错误的默认可重试性。 > 说明:错误码模型(`core/src/error_code.rs`)已建立并作为公共契约;下载、launcher/metadata、server-info/marker、配置校验、任务/RPC 等主要链路已接入该码表。剩余未实现命名空间和后续引擎能力继续按本表扩展。 ### 域一览 | 域 | 区间 | 含义 | |---|---|---| | input | `1xxxxx` | 输入/配置:CLI 参数、配置校验、代理配置 | | path_security | `2xxxxx` | 路径/安全边界:危险目录、路径逃逸、symlink、权限 | | network | `3xxxxx` | 网络/下载:HTTP/网络错误、代理故障、重试耗尽、quarantine | | integrity | `4xxxxx` | 校验/完整性:BLAKE3、官方 seed hash、size、ZIP 结构 | | publish_storage | `5xxxxx` | 发布/版本状态/存储:staging、原子发布、version-state、锁、CAS | | parse | `6xxxxx` | 解析/适配:manifest、UnityFS、GameMainConfig | | task_rpc | `7xxxxx` | 任务/RPC:未知方法、参数非法、未实现、任务不存在 | | internal | `9xxxxx` | 内部/未知:兜底 | ### 码表 | 码 | kind | 可重试 | 含义 | |---|---|:---:|---| | `BAT-ERR-100001` | missing_app_version | 否 | 缺少应用版本(未传 `--app-version` 且未启用 `--auto-discover`) | | `BAT-ERR-100002` | missing_connection_group | 否 | 缺少连接组 | | `BAT-ERR-100003` | missing_server_info_source | 否 | 缺少服务器信息来源 | | `BAT-ERR-100004` | invalid_proxy_scheme | 否 | 代理 URL scheme 不受支持 | | `BAT-ERR-100010` | invalid_argument | 否 | 命令行参数无效 | | `BAT-ERR-200001` | dangerous_output_root | 否 | 输出目录被判定为危险路径 | | `BAT-ERR-200002` | path_escape | 否 | 路径逃逸出允许根目录 | | `BAT-ERR-200003` | symlink_rejected | 否 | 目标不允许是 symlink 或路径组件含 symlink | | `BAT-ERR-200004` | file_permission | 否 | 文件权限或模式错误 | | `BAT-ERR-300001` | http_forbidden | 否 | HTTP 403 | | `BAT-ERR-300002` | http_not_found | 否 | HTTP 404 | | `BAT-ERR-300003` | http_client_error | 否 | HTTP 其它 4xx | | `BAT-ERR-300004` | http_too_many_requests | 是 | HTTP 429 / 请求过多 | | `BAT-ERR-300005` | http_server_error | 是 | HTTP 5xx | | `BAT-ERR-300010` | network_dns | 是 | DNS 解析失败 | | `BAT-ERR-300011` | network_connect | 是 | 连接失败 | | `BAT-ERR-300012` | network_timeout | 是 | 超时 | | `BAT-ERR-300013` | network_tls | 是 | TLS 失败 | | `BAT-ERR-300014` | network_interrupted | 是 | 传输中断 | | `BAT-ERR-300015` | network_other | 是 | 其它网络错误 | | `BAT-ERR-300020` | retry_exhausted | 否 | 下载重试次数耗尽 | | `BAT-ERR-300021` | quarantined | 否 | URL 因反复失败进入 quarantine | | `BAT-ERR-300030` | non_official_url | 否 | URL 不是官方 host(被拒绝) | | `BAT-ERR-300031` | launcher_api_rejected | 否 | 官方启动器 API 返回非 200 业务码(版本/鉴权被拒等) | | `BAT-ERR-310001` | proxy_failure | 否 | 代理自身故障(认证/解析/连接代理失败) | | `BAT-ERR-400001` | blake3_mismatch | 否 | 本地 BLAKE3 与 manifest 不符 | | `BAT-ERR-400002` | official_hash_mismatch | 否 | 官方 seed `.hash`(xxHash32)校验不符 | | `BAT-ERR-400003` | size_mismatch | 否 | 文件大小与 manifest 不符 | | `BAT-ERR-400004` | zip_structure_invalid | 否 | ZIP 结构无效 | | `BAT-ERR-500001` | resource_locked | 否 | 资源目录锁冲突(对应退出码 75) | | `BAT-ERR-500002` | staging_prepare_failed | 否 | staging 准备失败 | | `BAT-ERR-500003` | publish_failed | 否 | 原子发布失败 | | `BAT-ERR-500004` | version_state_write_failed | 是 | 版本状态写入失败 | | `BAT-ERR-500010` | cas_hash_mismatch | 否 | CAS 对象 Hash 不匹配 | | `BAT-ERR-500011` | cas_object_not_found | 否 | CAS 对象不存在 | | `BAT-ERR-500012` | cas_reference_underflow | 否 | CAS 引用计数下溢 | | `BAT-ERR-500013` | cas_database | 否 | CAS 元数据库错误 | | `BAT-ERR-600001` | manifest_parse_failed | 否 | Manifest / Addressables catalog 解析失败 | | `BAT-ERR-600002` | unityfs_parse_failed | 否 | UnityFS 解析失败 | | `BAT-ERR-600003` | game_main_config_failed | 否 | GameMainConfig 解密/解析失败 | | `BAT-ERR-600004` | launcher_response_invalid | 否 | 官方启动器链内容无效(API 响应、远端 manifest 或包内容无法解析/缺少必需内容) | | `BAT-ERR-700001` | rpc_unknown_method | 否 | 未知 RPC 方法 | | `BAT-ERR-700002` | rpc_invalid_params | 否 | RPC 参数无效 | | `BAT-ERR-700003` | rpc_not_implemented | 否 | 方法/命名空间尚未实现 | | `BAT-ERR-700004` | task_not_found | 否 | 任务不存在 | | `BAT-ERR-700005` | task_interrupted | 否 | 任务因 daemon 停止/重启而中断 | | `BAT-ERR-900001` | internal | 否 | 未归类的内部错误 | 新增错误码在 `core/src/error_code.rs` 的码表登记后,同步更新本表。 --- ## 6. Daemon RPC 接口 稳定 contract 以 `docs/reference/rpc-backend-api.md` 为准,本节保留常用说明和命令行示例。 `bat --daemon` 在后台状态目录下创建 `bat.sock`(Unix socket),提供**换行分隔的 JSON-RPC 2.0** 控制面。CLI 的 `status`/`stop`/`logs`/`reload`/`refresh`/`repair` 优先走它;Go 服务层也应通过这个进程边界调用,而非 FFI 或执行 `bat` binary 后再解析 stdout。 ### 传输与 envelope - 请求:一行 JSON-RPC 2.0,`{"jsonrpc":"2.0","id":,"method":".","params":{…}}`。 - 响应:JSON-RPC 2.0,应用层负载统一装入 `result` 的 envelope: ```json {"jsonrpc":"2.0","id":1,"result":{ "ok": true, "status": "ok", "data": { … }, "request_id": "req--" }} ``` - `ok`:应用层成功与否。失败时 `ok=false`、`status="error"`、`error` 为 §5 的 `ApiError` 结构(含 `BAT-ERR` 码)。 - `status`:`ok` | `accepted`(长任务已入队) | `error`。 - `request_id`:进程内唯一请求 ID。 - 请求解析失败(畸形 JSON)走 JSON-RPC 顶层 `error`(如 `-32700`),不进 envelope。 ### 方法命名空间 方法采用 `.`。`bat.*` 为兼容别名(解析为 `daemon.*`)。 | 方法 | 状态 | 说明 | |---|---|---| | `daemon.status` | ✅ | 后台状态快照 | | `daemon.logs` | ✅ | 日志尾部(`params.tail`,默认 200) | | `daemon.stop` | ✅ | 请求停止(`accepted`) | | `daemon.reload` | ✅ | 请求重新发现并强制刷新(`accepted`) | | `daemon.refresh` | ✅ | 请求刷新检查(`params.force`,`accepted`) | | `daemon.restart` | ✅ | 启动 Rust lifecycle controller,并在响应后停止当前 daemon(`accepted`) | | `daemon.doctor` | ✅ | 返回运行时诊断报告(只读,不清理、不重启) | | `resource.state` | ✅ | 资源发布根 + 版本状态 + 上次同步结果 | | `resource.sync` | ✅ | 触发同步任务(`params.force`),返回 `task_id` | | `resource.verify` | ✅ | 触发校验任务(dry-run + audit),返回 `task_id` | | `resource.repair` | ✅ | 触发本地 manifest 审计 + 修复任务,返回 `task_id`;不继承 `force` | | `resource.manifest` / `resource.list` | ✅ | 当前版本下载 manifest 分页查询(`params.offset` 默认 0、`params.limit` 默认 100/上限 1000) | | `resource.index` | ✅ | 查询现有 SQLite ResourceRepository 索引,支持资源类型、hash、路径模式、release、平台、destination、bundle path、archive entry、parse status 和 TextUnit format 过滤 | | `parse.status` | ✅ | 查询当前 release 的解析缓存、TextUnit 索引和队列摘要 | | `parse.text_units` / `parse.errors` | ✅ | 查询当前 release 的 TextUnit 明细和解析错误 | | `translation.tasks` | ✅ | 查询离线 TextUnit 翻译任务及 worker 状态 | | `translation.handoff` | ✅ | 查询完整 job/unit/provider run 交接视图 | | `translation.task.update` | ✅ | 回写当前 release 的 provider worker 状态 | | `translation.worker.run` | ✅ | 触发 Rust provider worker,落库 TextUnit 译文结果、lease、失败分类和重试状态 | | `translation.proofread` | ✅ | 将当前汉化 workflow 标记为人工校对中 | | `localized.status` | ✅ | 查询汉化 release 与当前官方 release 的匹配状态 | | `catalog.status` | ✅ | 当前已发布版本的 catalog 概览(app/bundle 版本、addressables 根、端点与 marker 计数、launcher 元数据) | | `catalog.versions` | ✅ | 版本历史:current / in_progress / previous / failed | | `catalog.diff` | ✅ | 当前 snapshot 相对上一个可用版本的差异(base_delta + extended_delta + 变更端点 URL) | | `catalog.refresh` | ✅ | 触发 catalog 更新检查任务(dry-run 计划,不下载;`params.force`),返回 `task_id` | | `task.status` | ✅ | 查询任务(`params.task_id`) | | `task.list` | ✅ | 列出全部任务(最新在前) | | `task.cancel` | ✅ | 请求取消任务(`params.task_id`);协作式,在同步检查点生效 | | `task.logs` | ✅ | 返回任务的进度日志(`params.task_id`,有界) | | `patch.apply` | ✅ | 对显式 source/patch/target 文件同步执行 Binary/JSON/Text patch | | `unityfs.patch_text_asset` / `unityfs.patch_string_field` / `unityfs.patch_field` | ✅ | 对显式 UnityFS bundle 文件执行文件级写入并原子输出 | | `daemon.clean-stable` / 发布级 patch 方法 / 其他未开放 `unityfs.*` / `task.create` | ⏳ | 返回 `BAT-ERR-700003`(not implemented);clean-stable 仍由 CLI 侧按进程生命周期显式执行,task.create 暂不开放通用任务入口 | | 未知方法 | — | `BAT-ERR-700001`(unknown method) | 只读查询(`daemon.doctor` / `resource.state` / `resource.manifest` / `resource.list` / `resource.index` / `parse.*` / `translation.tasks` / `translation.handoff` / `localized.status` / `catalog.status` / `catalog.versions` / `catalog.diff`)在尚无已发布版本 或对应文件不存在时返回 `ok: true` 且 `data.available: false`(正常状态而非错误,便于调用方直接分支)。 ### 任务模型 `resource.sync` / `resource.verify` / `resource.repair` / `catalog.refresh` 是**异步任务**:入队即返回 `{ "task_id": "task--", "kind": "resource.sync" }`(`status: "accepted"`),实际执行由后台任务 worker 串行完成,通过 `task.status` / `task.list` 轮询。任务记录: ```json { "id": "task-1234-1", "kind": "resource.sync", "status": "queued|running|succeeded|failed|cancelled", "stage": "download", "message": "…", "created_at": …, "updated_at": …, "started_at": …, "finished_at": …, "error": { … }, "result": { … } } ``` - `task.cancel` 请求取消:置任务的取消标志,worker 在下一个同步检查点中止,任务转为 `cancelled`(协作式,不硬杀正在执行的 curl)。 - 与后台 watch 循环的定时同步通过进程内锁互斥(任务等待而非失败)。 - 任务历史**持久化**在 `/bat-tasks.json`(版本化、`0600` 原子写):生命周期转换(入队/开始/结束)时落盘,进行中任务的 `stage`/`message`/日志以内存实时值为准、随下一次转换写入。daemon 重启后历史任务经 `task.status` / `task.list` / `task.logs` 仍可查;重启时仍处于 `queued`/`running` 的任务标记为 `failed`(错误码 `BAT-ERR-700005` task_interrupted)。文件损坏时改名 `bat-tasks.json.corrupt` 留证并从空历史开始。历史保留最近 64 条(运行中任务不裁剪)。 ### 示例 ```bash # 触发同步任务并取回 task_id(socat 演示) printf '{"jsonrpc":"2.0","id":1,"method":"resource.sync","params":{"force":true}}\n' \ | socat - UNIX-CONNECT:/tmp/bat-pid/bat.sock # 轮询任务 printf '{"jsonrpc":"2.0","id":2,"method":"task.status","params":{"task_id":"task-1234-1"}}\n' \ | socat - UNIX-CONNECT:/tmp/bat-pid/bat.sock # 查询当前 catalog 概览与版本历史 printf '{"jsonrpc":"2.0","id":3,"method":"catalog.status"}\n' \ | socat - UNIX-CONNECT:/tmp/bat-pid/bat.sock printf '{"jsonrpc":"2.0","id":4,"method":"catalog.versions"}\n' \ | socat - UNIX-CONNECT:/tmp/bat-pid/bat.sock # 分页读取当前版本的下载 manifest printf '{"jsonrpc":"2.0","id":5,"method":"resource.manifest","params":{"offset":0,"limit":50}}\n' \ | socat - UNIX-CONNECT:/tmp/bat-pid/bat.sock # 触发本地资源审计+修复任务 printf '{"jsonrpc":"2.0","id":6,"method":"resource.repair"}\n' \ | socat - UNIX-CONNECT:/tmp/bat-pid/bat.sock ```