Skip to content

Beta Features

DNT_OF edited this page Oct 4, 2026 · 1 revision

内测功能(2.6.1 RIDGE)

2.6.1 RIDGE 是预发布版本(GitHub Pre-release,tag v2.6.1_RIDGE,正式发布后可用)。本页的两项功能默认全部关闭;不开开关时行为与稳定版 2.6.0 PEAK 一致(文件沙箱的链接防护除外,见 Security-Model)。

内测功能只在维护者本机做过加载冒烟与无鉴权探测,带鉴权的端到端流程尚未完整测试。请只在测试服打开开关,发现问题请 开 Issue。


开关

键(config.yml) 默认 打开后
beta_adapted_plugin_actions false POST /control/adapted/<plugin_id>/<action> 可用;/plugins/adapted 列出 actions
beta_file_root_ws false /control/files/stat、read_chunk、write_chunk 可用(仍需配置 file_root)
  • 升级到 2.6.1 后首次加载,LabAPI 会把两个键以 false 写进 config.yml。
  • 改完必须重启服务器才生效(见 Configuration)。
  • 开关关闭时,上述端点一律 404(内测端点未开启(config: ...: false))。
  • 打开任一开关时,启动日志会打一条 [SLDataAPI] 内测功能已开启…… 警告。
  • 两类端点都属于控制面:需 control_enabled: true,HTTP /control/* 与 WS call 走同一路由(受 control_transport 互斥约束),鉴权、ACL、审计与其他 /control/* 一致。

权限(ACL)

新增 / 涉及的端点默认拒绝,内置 admin、duty 模板以及 all_control_true 都不会自动授予:

ACL 键 覆盖 默认
/control/adapted/ 全部适配插件动作 拒绝
/control/adapted/<plugin_id>/ 单个插件的全部动作 未定义(按上一条)
/control/adapted/<plugin_id>/<action> 单个动作(精确) 未定义
/control/files/ files/list|read|write 与新增的 stat|read_chunk|write_chunk 拒绝

按 Key 显式放开(apikey.config → keys[].endpoints_override,最长前缀匹配,越具体越优先):

keys:
  - id: platform
    template: admin
    fingerprint: "sha256:..."     # 由 sldataapi apikey create 写入,勿手改
    endpoints_override:
      "/control/adapted/dntof.sample_adapted/": true    # 只放开示例插件
      "/control/files/": { read: true, write: false }   # 文件只读(stat / read_chunk / list / read)
  • 全部适配插件:"/control/adapted/": true;在全放开的同时禁掉某个插件:再加 "/control/adapted/<id>/": false。
  • 读写判定:files/stat、files/read_chunk(及 list、read)算读;files/write_chunk 与全部 /control/adapted/* 一律算写。
  • 修改 apikey.config 后建议重启服务器。也可以改文件里的 endpoint_catalog 让 admin 模板默认获得 /control/adapted/,但不推荐——按 Key 授权更可控。

一、适配插件写操作(beta_adapted_plugin_actions)

在只读发现(GET /plugins/adapted、GET /plugins/<id>/<route>,见 HTTP-API)之外,适配插件可以注册写 / 动作路由,经控制面调用。插件侧用法见 Development-Guide · 适配插件集成。

调用

curl -s -X POST "http://<host>:8081/control/adapted/dntof.sample_adapted/bump" \
  -H "Authorization: Bearer YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"by":3}'

WS(control_transport: ws):

{"type":"call","reqId":"a1","path":"/control/adapted/dntof.sample_adapted/bump","body":{"by":3}}
项 值
路径 /control/adapted/<plugin_id>/<action>,恰好两段;plugin_id 形如 ^[a-zA-Z0-9][a-zA-Z0-9._-]{0,63}$,action 形如 ^[a-zA-Z0-9][a-zA-Z0-9_-]{0,63}$(大小写不敏感匹配)
请求体 任意 JSON(空体视为 {}),≤64KB;非 JSON → 400
执行 Unity 主线程,超时 3s
每插件动作数 ≤16
审计 一律按写操作,每次调用写入 control_log(actor = Key id)
插件返回体 ≤64KB;非 JSON 文本按字符串返回

成功(200):

{"success":true,"message":"ok","data":{"plugin_id":"dntof.sample_adapted","action":"bump","result":{"bumps":3}}}

result 为插件返回的 JSON;插件返回 null 时为 null。

状态 场景
400 请求体不是 JSON;路径字符非法;插件抛 AdaptedActionException(默认 400)
4xx 插件抛 AdaptedActionException(message, statusCode)(仅 400–499 生效,其他值按 400)
403 Key 未获授权(见上文 ACL)
404 开关关闭;路径不是两段;插件未注册;动作不存在
413 请求体或返回体超过 64KB
500 插件处理器抛出其他异常
504 主线程派发超时 / 失败

失败时 message 为插件或注册表给出的原因(如 by must be 1..100、action not found)。

发现

开关打开时,GET /plugins/adapted 与 get_sl_data.adapted_plugins[*] 每项多一个 actions 字段(动作名数组;内置探测包装 SLPlayer / OmegaWarhead 为 [],且不能追加动作)。开关关闭时该字段整体省略,只读发现的结构不变。


二、FileRoot 的 WS 适配(beta_file_root_ws)

原有 files/list|read|write 本来就能走 WS call,但单条消息有上限(WS 256KB、HTTP 请求体 64KB),而文件读上限 1MB、写上限 512KB,接近上限的配置文件无法一次传完。新增三个端点用分块解决。

共同约束(与原文件端点完全一致):

  • 必须配置 file_root(为空 → 404 文件端点未启用)
  • 路径相对 file_root;拒绝 .. 越界、:、符号链接 / junction;禁止 Windows 系统目录、游戏数据目录、SLDataAPI 自身配置目录
  • 只允许配置类扩展名:yml yaml txt json cfg ini conf config xml properties
  • 参数错误统一 400 + 中文 message
  • 纯 IO,不派发主线程

POST /control/files/stat(读)

请求:{"path":"configs/a.yml"}

文件:

{"path":"configs/a.yml","type":"file","size":1234,"modified":"2026-10-04 01:02:03","protected":false,
 "sha256":"<hex>","max_read_bytes":1048576,"max_write_bytes":524288,"max_chunk_bytes":163840}

目录:{"path":"configs","type":"dir","size":0,"modified":"...","protected":false,"sha256":null}(protected 为 true 表示受保护目录)。

modified 为 UTC,格式 yyyy-MM-dd HH:mm:ss。文件超过 1MB 时 sha256 为 null。非配置扩展名的文件 → 400。

POST /control/files/read_chunk(读)

字段 说明
path 必填
offset 可选,默认 0;须在 0..size 内
length 可选,默认 65536;上限 163840(160KB),超出按上限截断

响应 data:

{"path":"configs/a.yml","size":300000,"offset":0,"length":65536,"next_offset":65536,"eof":false,
 "data":"<base64>","sha256":"<整文件 sha256,仅 offset 为 0 时给出,否则 null>"}

循环用 next_offset 续读直到 eof: true;拼接后与首块的 sha256 比对。文件 >1MB 拒绝读取。

POST /control/files/write_chunk(写)

分块上传会话:

字段 说明
path 必填;每块都要带,且与会话一致
action 可选:append(默认)/ abort
upload_id 首块省略(服务器新建会话并返回);后续块必填
offset 本块起始字节;必须等于已接收字节数(首块为 0)
data 本块内容,base64
final 可选 bool;为 true 时提交写入
sha256 可选;final 时校验整份内容(hex,大小写不敏感),不符则不写入

限制:整份 ≤512KB;会话 120s 无活动过期;每把 Key 最多 2 个未完成会话,全服最多 8 个;会话绑定 Key 与 path。内容必须是合法 UTF-8 文本;提交时先写同目录临时文件再替换(原子写入)。首块就会做完全部写入防线检查,越界或受保护路径立即拒绝。

响应 data:

场景 data
非最后一块 {"upload_id":"up_<hex>","received":65536,"committed":false}
final: true {"upload_id":"up_...","received":300000,"committed":true,"file":{"path":"...","bytes":300000,"sha256":"<hex>"}}
action: "abort" {"upload_id":"up_...","aborted":true}(只能取消自己 Key 的会话;不存在或已过期时 aborted:false)

单块大小建议:WS 下 ≤160KB 原始字节(base64 后仍在 256KB 消息上限内);HTTP 下请求体 ≤64KB,单块约 ≤45KB。

审计:write_chunk 每次调用都记入 control_log,但其中的 data 只记录长度(<base64 N chars>),避免撑大日志。stat / read_chunk 是读操作,不记审计。

服务器卸载插件(重启)时,未完成的上传会话全部丢弃。


三、WS hello 的 beta 数组

控制 WS 握手后的 hello 新增 beta,列出当前已开启的内测能力:

{"type":"hello","server":"SLDataAPI","version":"2.6.1","endpoints":"/control/*","beta":["adapted_actions","file_chunks"]}
值 对应开关
adapted_actions beta_adapted_plugin_actions
file_chunks beta_file_root_ws

都关闭时为 []。平台可据此决定是否展示相关 UI;file_chunks 只表示开关已开,file_root 是否配置请以 files/stat 的结果为准。协议其余部分见 WS-Control-Protocol。


相关:HTTP-API · Configuration · Security-Model · Development-Guide

Clone this wiki locally