16 KiB
Rust Resource Backend RPC API
本文档冻结本机 Rust Resource Backend API 的稳定调用边界。Go 项目
bat-api、Go 服务层、运维脚本和 bat CLI 都应以这里的 JSON-RPC
contract 为准,不应绕过 daemon 状态文件或扩展 bat-ffi 作为主路径。
传输
- 传输:Unix domain socket。
- 默认 socket:
/tmp/bat-pid/bat.sock。 - 协议:JSON-RPC 2.0,每行一个 request,每行一个 response。
- 编码:UTF-8 JSON。
- 访问控制:依赖本机文件权限和状态目录权限;不要把 socket 暴露到公网。
请求:
{"jsonrpc":"2.0","id":1,"method":"resource.repair","params":null}
成功响应的 JSON-RPC 顶层 result 一律是应用层 envelope:
{
"jsonrpc": "2.0",
"id": 1,
"result": {
"ok": true,
"status": "accepted",
"data": {"task_id": "task-1234-1", "kind": "resource.repair"},
"request_id": "req-1234-1"
}
}
应用层失败也放在 result 的 envelope 中:
{
"ok": false,
"status": "error",
"error": {
"code": "BAT-ERR-700003",
"kind": "not_implemented",
"domain": "rpc",
"location": "rpc.dispatch",
"message": "方法尚未实现:daemon.clean-stable",
"retryable": false
},
"request_id": "req-1234-2"
}
只有 JSON 解析失败等传输层错误使用 JSON-RPC 顶层 error。
Envelope
| 字段 | 类型 | 说明 |
|---|---|---|
ok |
bool | 应用层是否成功。 |
status |
string | ok、accepted 或 error。 |
data |
object/null | 成功结果。失败时省略。 |
error |
object/null | ApiError。成功时省略。 |
request_id |
string | daemon 进程内请求 ID,用于日志关联。 |
ApiError 结构以 core/src/error_code.rs 码表为准:
| 字段 | 类型 | 说明 |
|---|---|---|
code |
string | BAT-ERR-<6位>。 |
kind |
string | 错误类别。 |
domain |
string | 错误域。 |
location |
string | Rust 侧出错位置。 |
message |
string | 可诊断错误信息。 |
retryable |
bool | 调用方是否可以按策略重试。 |
方法
daemon
| 方法 | 状态 | params | data |
|---|---|---|---|
daemon.status |
已实现 | null |
后台状态报告。 |
daemon.logs |
已实现 | { "tail": 200 } |
日志尾部报告。 |
daemon.stop |
已实现 | null |
accepted ack。 |
daemon.restart |
已实现 | null |
accepted ack;启动 Rust lifecycle controller,并在响应后停止当前 daemon。 |
daemon.reload |
已实现 | null |
accepted ack。 |
daemon.refresh |
已实现 | { "force": false } |
accepted ack。 |
daemon.doctor |
已实现 | null |
只读诊断报告。 |
daemon.clean-stable |
保留 | null |
live RPC 不执行;由 CLI 离线清理入口处理。 |
daemon.restart 不在 daemon 线程内手写第二套启动流程;它启动本机 Rust
bat restart --state-dir ... lifecycle controller,由既有 CLI restart 路径复用
保存的启动参数、代理凭据、PID/socket 替换和控制锁。
bat.status、bat.stop、bat.restart、bat.reload、bat.refresh、bat.logs、
bat.doctor、bat.clean-stable 是兼容别名;新代码应使用 daemon.*。
resource
| 方法 | 状态 | params | data |
|---|---|---|---|
resource.state |
已实现 | null |
资源发布根、版本状态、上次同步结果。 |
resource.sync |
已实现 | { "force": false } |
{ "task_id": "...", "kind": "resource.sync" }。 |
resource.verify |
已实现 | null |
{ "task_id": "...", "kind": "resource.verify" }。 |
resource.repair |
已实现 | null |
{ "task_id": "...", "kind": "resource.repair" }。 |
resource.manifest |
已实现 | { "offset": 0, "limit": 100 } |
当前 download manifest 分页。 |
resource.list |
已实现 | { "offset": 0, "limit": 100 } |
resource.manifest 的兼容别名。 |
resource.index |
已实现 | { "offset": 0, "limit": 100, "type": "asset_bundle", "hash": "...", "path_pattern": "*" } |
当前 ResourceRepository 分页/过滤查询。 |
resource.repair 会开启本地 manifest audit + repair,不继承 force。
resource.manifest / resource.list 查询当前已发布 release 的
official-download-manifest.json;resource.index 查询可选导入产生的
SQLite ResourceRepository,索引不存在时返回 ok=true 且
data.available=false,不会隐式创建数据库。limit 范围是 1..=1000,
非法参数返回 BAT-ERR-700002。
resource.index 的 entries[] 是 Resource JSON,除 id、local_path、
entry 外会包含 metadata:official_release_id、platform、
bundle_path、archive_entries、parse_statuses、unity_versions、
text_assets、text_unit_count、text_unit_formats 和
text_unit_error_count 等字段。旧索引库会通过 metadata_json 迁移列得到
默认空 metadata。
resource.state、catalog.status、parse.status 和 localized.status
都会返回当前观察面的短状态 status 与稳定状态码 status_code。status_code
使用命名空间格式,例如 official.up_to_date、official.published、
parse.completed、translation.queued_offline、localized.published 和
distribution.ready。这些状态码描述资源/解析/翻译 handoff/汉化/分发生命周期;
失败原因仍使用 BAT-ERR-* 错误码,二者不混用。响应还会包含
status_phase、status_terminal 和 status_retryable,供 bat-api 等读侧
决定展示、重试或 readiness。
官方资源完整新版本发布后,Rust 侧会先比较上一完整 release 与当前 release 的 download manifest,并在当前 release 根目录写出:
official-resource-changes.json:记录 added / modified / removed 资源。 同一 destination 只有 size 或 BLAKE3 变化才算 modified;URL 或 CDN root 变化但内容一致时不进入解析/翻译候选。crowdin-translation-handoff.json:只包含 added + modified 资源,作为后续 Crowdin worker 的稳定本地队列输入;当前 RPC 不直接调用 Crowdin API。official-parse-cache.json:解析缓存。up-to-date 轮询发现本地文件未变且缓存 有效时只读取摘要,不重复解析。official-textunit-index.json:TextUnit 明细和解析错误索引。up-to-date 轮询发现 本地文件未变且索引有效时复用,不重复解析。official-textunit-tasks.json:只由 added + modified 资源、parse cache 和 TextUnit 明细索引派生,记录 TextUnit 任务、跳过原因和解析诊断。crowdin-textunit-queue.json:只包含已产生 TextUnit 的离线任务,预留给后续 Crowdin worker;当前不会发出网络请求。
删除资源只进入 official-resource-changes.json,不进入 Crowdin handoff。
parse
| 方法 | 状态 | params | data |
|---|---|---|---|
parse.status |
已实现 | null |
当前官方 release 的解析缓存状态。 |
parse.text_units |
已实现 | { "offset": 0, "limit": 100, "destination": "*Table*", "archive_entry": "*.bytes", "path_id": 1, "class_id": 114, "field_path": "*Text*", "format": "json" } |
当前官方 release 的 TextUnit 明细分页。 |
parse.errors |
已实现 | { "offset": 0, "limit": 100, "destination": "*Table*", "archive_entry": "*.bytes", "path_id": 1, "class_id": 114, "field_path": "*Text*", "format": "json" } |
当前官方 release 的解析错误分页。 |
parse.status 是只读查询;没有当前 release 或没有解析缓存时返回
ok=true 且 data.available=false。解析缓存来自官方原版资源目录,不读取
汉化输出目录。存在 official-textunit-index.json 时,响应会包含
textunit_index_available=true、textunit_index_path 和
textunit_index_summary;存在 official-textunit-tasks.json 时,响应会包含
textunit_queue_available=true、textunit_task_queue_path 和
textunit_task_summary。当 TextUnit 队列存在且有离线任务时,
translation_status_code=translation.queued_offline;真实 Crowdin worker
尚未接入时不会返回翻译完成状态。
parse.text_units / parse.errors 是只读查询;没有当前 release 或没有
official-textunit-index.json 时返回 ok=true 且 data.available=false。
分页参数 offset 默认 0,limit 默认 100,范围是 1..=1000。过滤参数:
| 字段 | 类型 | 说明 |
|---|---|---|
destination |
string | official download manifest destination,支持 * 通配。 |
archive_entry |
string | zip 内条目,支持 * 通配;直接 bundle 通常为 null。 |
path_id |
integer | Unity object path id。 |
class_id |
integer | Unity class id。 |
field_path |
string | TypeTree/TextAsset 字段路径,支持 * 通配。 |
format |
string | TextUnit 格式,例如 json、csv、tsv、plain 或 typetree_string。 |
parse.text_units 的 entries[] 会包含 source text、source URL、
destination、archive entry、source kind、Unity version、serialized file、
path id、class id、field path、字段 offset/byte size、format、asset name 和
context。parse.errors 的 entries[] 会包含 source URL、destination、
archive entry、status、serialized file、path id、class id、field path、
offset 和 error。TypeTree-covered managed reference 字段会进入结构化字段遍历;
完整 managed reference registry 等暂不支持结构会进入解析错误,而不是静默降级为
低保真文本。
localized
| 方法 | 状态 | params | data |
|---|---|---|---|
localized.status |
已实现 | null |
汉化发布状态、当前官方 release 匹配关系和汉化输出目录。 |
localized.status 严格按 daemon / .env 中的 BAT_LOCALIZED_OUTPUT 或
--localized-output 查询汉化产物目录,不把 ./bat-resources 与
./bat-localized 混用。当前支持未汉化发布状态和已汉化发布状态的只读报告。
返回 localized 的条件是:localized-version-state.json 的官方 release ID
匹配当前官方 release,current symlink 指向汉化发布根下对应的
versions/<id>,并且该版本目录中的
localized-patch-manifest.json 存在且 release ID 匹配。响应会返回
patch_manifest_path、patch_manifest_available、
patch_manifest_matches_release、patch_file_count、
patch_text_asset_operation_count 和 rollback_previous_current_target。
catalog
| 方法 | 状态 | params | data |
|---|---|---|---|
catalog.status |
已实现 | null |
当前已发布 catalog 概览。 |
catalog.versions |
已实现 | null |
current / in_progress / previous / failed。 |
catalog.diff |
已实现 | null |
当前 snapshot 相对上一可用版本的差异。 |
catalog.refresh |
已实现 | { "force": false } |
{ "task_id": "...", "kind": "catalog.refresh" }。 |
只读查询在没有可用版本时返回 ok=true 且 data.available=false。
catalog.status 可用时会返回 status_code=official.published,并用
distribution_status_code=distribution.ready 表示该官方 release 可被读侧分发;
不可用时对应 official.unavailable / distribution.blocked。
task
| 方法 | 状态 | params | data |
|---|---|---|---|
task.status |
已实现 | { "task_id": "..." } |
单个任务记录。 |
task.list |
已实现 | null |
{ "tasks": [...] }。 |
task.cancel |
已实现 | { "task_id": "..." } |
cancel ack。 |
task.logs |
已实现 | { "task_id": "..." } |
{ "task_id": "...", "lines": [...] }。 |
task.create |
保留 | object | 不开放通用任务入口;由语义方法创建任务。 |
任务记录:
{
"id": "task-1234-1",
"kind": "resource.repair",
"status": "queued",
"stage": null,
"message": null,
"created_at": 1780000000,
"updated_at": 1780000000,
"started_at": null,
"finished_at": null,
"error": null,
"result": null
}
status 取值:queued、running、succeeded、failed、cancelled。
daemon 重启后仍处于 queued 或 running 的历史任务会被标记为
failed,错误码为 BAT-ERR-700005。
patch / unityfs
已开放的文件级写入方法:
patch.apply:对显式source_path、patch_path、target_path执行 Binary/JSON/Text patch apply,kind取值为binary、json或text。unityfs.patch_text_asset:对显式 UnityFSbundle_path中的serialized_file_path/path_idTextAsset 应用replacement_path,写入target_path,可选expected_name。unityfs.patch_string_field:对显式 UnityFSbundle_path中的serialized_file_path/path_id/field_pathTypeTree string 字段应用replacement_text或 UTF-8replacement_path,写入target_path,可选expected_value。unityfs.patch_field:对显式 UnityFSbundle_path中的serialized_file_path/path_id/field_pathTypeTree 字段应用语义replacementJSON,写入target_path,可选expected_value。replacement使用{"kind":"signed","value":42}这类 tagged JSON;支持bool、signed、unsigned、float32、float64、string、bytes、enum、bit_field、p_ptr、固定 Unity 叶子结构、object 字段组合和 TypeTree schema 支撑的 array/map 整体替换。enum 形如{"kind":"enum","value":{"type_name":"ScenarioDifficulty","storage_type":"int","value":3}};type_name是 TypeTree enum 类型名,storage_type是 backing integer 类型。LayerMask/BitField形如{"kind":"bit_field","value":{"type_name":"LayerMask","storage_type":"UInt32","bits":9}}。 array 形如{"kind":"array","value":[{"kind":"string","value":"你好"}]};map entry 用 object 表达,例如{"kind":"object","value":[{"name":"first","value":{"kind":"string","value":"jp"}}]}。 扩容时复用当前首个元素或 TypeTree data node 的编码 schema;map entry schema 变化、unknown 字段和未覆盖的 managed reference registry 变体仍会返回明确错误。 固定 Unity 叶子结构使用 raw bits/bytes 表达,例如{"kind":"float32_struct","value":{"type_name":"Vector3f","values":[1065353216,1073741824,1077936128]}}或{"kind":"fixed_bytes","value":{"type_name":"GUID","bytes":[0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15]}}。
这些方法同步执行,不进入 task.* 队列;输出文件使用临时文件原子写入,响应
data 会返回 source / patch 或 replacement / target 的 size 与 BLAKE3。target_path
不能与输入文件相同。
仍关闭的范围:发布级 patch build / patch rollback、复杂 UnityFS 语义编辑、
unityfs.inspect、通用 manifest 驱动 release 切换。调用这些规划方法仍返回
BAT-ERR-700003。
CLI 对应关系:
| CLI | RPC |
|---|---|
bat patch-apply |
patch.apply |
bat unityfs-patch-text-asset |
unityfs.patch_text_asset |
bat unityfs-patch-string-field |
unityfs.patch_string_field |
bat unityfs-patch-field |
unityfs.patch_field |
Go 调用边界
bat-api 应直接调用本 RPC contract,不通过 exec 调用 bat binary。
bat binary 是人类 CLI 和进程生命周期工具;默认 refresh / repair
在 daemon 可用时也会作为 RPC client 调用同一个 socket。daemon.restart
会启动 Rust lifecycle controller 复用同一套 CLI restart 路径,Go 层仍不直接
exec 或解析 bat stdout。
人类 CLI 的只读查询命令与 RPC 对应关系如下:
| CLI | RPC |
|---|---|
bat parse-status |
parse.status |
bat parse-text-units |
parse.text_units |
bat parse-errors |
parse.errors |
bat localized-status |
localized.status |
bat resource-index |
resource.index |
bat resource-index 支持 --offset、--limit、--resource-type、--hash
和 --path-pattern;bat parse-text-units / bat parse-errors 支持
--offset、--limit、--destination、--archive-entry、--path-id、
--class-id、--field-path 和 --format;这些过滤参数不适用于
parse-status 或 localized-status。
Go mirror contract fixture 固化在 internal/api/testdata/contract/,覆盖
catalog.status available/unavailable、resource.manifest page0 和对应
official-sync-snapshot.json。这些 fixture 由 Rust 输出归一化而来,只用于
schema / mirror 回归;live daemon socket 和完整 release 切换仍需在允许 smoke 的
隔离环境中验证。
禁止事项:
- Go 服务层不直接读写
bat-status.json、bat-tasks.json等 daemon 内部状态文件。 - Go 服务层不扩展
bat-ffi为主控制面。 - Go 服务层不通过 stdout 解析
bat status --json作为常规调用路径。