configSchema、分组、密钥和 pluginEnv()。
密钥和选项在工作台的设置页里填。点图标轨底部的齿轮,在弹出层里选「设置」,再选中你的插件,改完点「保存」。配置写在用户数据目录的 plugin-settings.json,按插件 id 分开。覆盖安装不会清掉它。用户卸载已安装的插件之后,对应的一块会被删掉。用「加载本地目录」挂上的实例不能从界面当已安装插件卸载,配置会留着。
缓存、导出文件和数据库不进 plugin-settings.json。它们的位置见 数据。
工作台不读 .env,也不替你写 .env。脚本本身只认环境变量,不引用 Dex Buddy:
- 在工作台里跑:声明了
runtime时,用ctx.runtime.python或ctx.runtime.node,环境传{ env: ctx.runtime.env }。没有声明运行时,才传{ env: ctx.pluginEnv() }。设置页里的值在这两种环境里都有。虚拟环境在ctx.runtime.env里。声明了externalTools且没有runtime时,这些命令的目录在pluginEnv()的 PATH 前面;声明了runtime时在ctx.runtime.env里。 - 离开工作台单独跑:脚本自己加载项目里的
.env。已有的环境变量优先,这样工作台注入的值不会被.env盖掉。
.env 可以留在你自己的仓库里做本地调试,不要打进 zip。
Python 示例:
import os
from dotenv import load_dotenv
load_dotenv(override=False)
api_key = os.getenv("MY_SERVICE_TOKEN")
tts_engine = os.getenv("TTS_ENGINE", "edge-tts")configSchema 的键名就是环境变量名:以大写字母开头,只含大写字母、数字和下划线。
{
"configSchema": {
"MY_SERVICE_TOKEN": {
"type": "string",
"title": "服务令牌",
"description": "插件自己的第三方服务令牌,不是 Dex Buddy 网关 Key",
"default": "",
"secret": true,
"group": "模型"
},
"TTS_ENGINE": {
"type": "select",
"title": "语音合成引擎",
"options": ["edge-tts", "azure-tts"],
"default": "edge-tts",
"group": "语音"
},
"MAX_RETRY": {
"type": "number",
"title": "最大重试次数",
"default": 3
}
}
}string:单行文本。"secret": true时,正在输入显示明文,保存之后变成圆点。点输入框旁的眼睛可以查看已保存的明文,再点藏回圆点。插件自己的页面仍然读不到明文。留空保存会保留原密钥,要点「清除」才变成空字符串。group:可选。去掉首尾空白后 1–32 个字符。不写或空字符串时,这一项归入「通用配置」。详见下面「分组怎么排」。boolean:开关。number:数字。select:options是非空字符串数组,default必须是其中一项。path:目录。设置页的「更改」打开系统目录选择。要填文件路径时用string。
title 必填,description 可以不写。
分组怎么排
上面这份声明在设置页上是三块,顺序跟字段第一次出现的位置一致,不按组名字母排:先是「模型」(密钥),再是「语音」(语音引擎),最后是「通用配置」(只有最大重试次数,因为它没写 group)。组名在框外,这一组的字段收在同一个圆角框里。
- 组的位置是这个名字第一次出现的地方。「通用配置」不固定在最前或最后。每一项都写了
group时,不显示空的「通用配置」。 - 去掉首尾空白后文字相同,就合成同一个框。框里的字段仍按它们在 JSON 里的先后排列。中间夹着别的组时,后面的同名项并回先出现的那一块,不会再画第二个标题。
" 模型 "和"模型"是一组。写成"通用配置"就并进默认那一块,不会出现两个标题。大小写不同是两组,例如"Model"和"model"。 - 组只有标题,一直展开。不能给组另写说明,也不能单独指定组的顺序。
- 组名不写入
plugin-settings.json。改组名、拆组、并组都不迁移,也不删除已保存的值。saveSettings只提交values和secrets,自定义设置页不用传group。group不进getPluginConfig(),也不进pluginEnv()。
某一项的 group 超过 32 个字符,或不是字符串,整份 configSchema 这次不可用。插件仍然加载,设置页说明问题,getPluginConfig() 返回空对象,pluginEnv() 不带这些键。磁盘上的 plugin-settings.json 不删。改好声明并重启后,原来的键还会注入。其它字段声明写错也是这样:整份声明暂时不注入,已保存的值留在磁盘上。
接入时按这个顺序:
- 在
plugin.manifest.json写configSchema。键名必须和脚本里os.getenv或process.env的名字一致。 - 改了 manifest 要重启 Dex Buddy。重启后,从图标轨齿轮弹出层进入「设置」,就会看到这个插件。
- 在设置页填完,点「保存」。宿主只写入
plugin-settings.json,不发保存事件,也不重跑apply。之后再调ctx.pluginEnv()或getPluginConfig()就是新值,不用为了改一项再重启 Dex Buddy。不要在apply里把返回值抄进变量或闭包后一直用;要新值就在真正用到密钥或选项时再读一次。apply里一直活着的子进程还拿着启动时传入的环境,要自己把它停掉再拉起,并在拉起时再传一次环境。 - 声明了
runtime时,execFile或spawn用ctx.runtime.python或ctx.runtime.node,并传入{ env: ctx.runtime.env }。没有声明运行时,才传入{ env: ctx.pluginEnv() }。漏传时,脚本只能看到 Dex Buddy 进程自己的环境,看不到设置页里的值,也找不到装进去的包。写法见 运行。 - 日志里不要打印密钥。
settingsEntry 指向插件目录里的 HTML。有合法声明时,设置页上面是生成的表单,下面是这个页面。只有自带页面、没有合法声明时,设置页只显示这个页面。页面没有 Node,读写的是同一块配置,而且读不到其他插件,也读不到已保存的密钥明文。明文只在工作台设置页点眼睛时取出:
const current = await window.dex.readSettings();
const saved = await window.dex.saveSettings({
values: { TTS_ENGINE: 'edge-tts', MAX_RETRY: 3 },
secrets: { MY_SERVICE_TOKEN: { action: 'keep' } },
});secrets 里 keep 表示不改,set 写入新字符串,clear 写成空字符串。整节里有一项不合法时,这一次不会写入。