#
服务器插件
这些插件允许添加使用 UI 扩展单独无法实现的功能,例如创建新的 API 端点或使用在浏览器环境中不可用的 Node.JS 包。
插件包含在 SillyTavern 的 plugins 目录中,并在服务器启动时加载,但仅当 config.yaml 文件中的 enableServerPlugins 设置为 true 时才会加载。
警告
服务器插件没有沙盒保护。这意味着它们可能潜在地获得对您整个文件系统的访问权限,或者以普通 UI 扩展无法的方式引入广泛的安全漏洞。只安装来自您信任的开发者的服务器插件!
有关所有官方服务器插件的列表,请参见 GitHub 组织列表:https://github.com/search?q=topic%3Aplugin+org%3ASillyTavern&type=Repositories
#
插件类型
#
文件
一个可执行的 JavaScript 文件,带有 ".js"(用于 CommonJS 模块)或 ".mjs"(用于 ES 模块)扩展名,包含一个导出 init 函数的模块。此函数接受一个 Express 路由器(专门为您的插件创建)作为参数并返回一个 Promise。
该模块还应导出一个包含有关插件信息的 info 对象(id、name 和 description 字符串)。这将为加载器提供有关插件的信息。
您可以通过路由器注册路由,这些路由将在 /api/plugins/{id}/{route} 路径下注册。例如,example 插件的 router.get('/foo') 将产生这样的路由:/api/plugins/example/foo。
插件还可以可选地导出一个 exit 函数,该函数在关闭服务器时执行清理。它应该没有参数并且必须返回一个 Promise。
插件导出的 TypeScript 合约:
interface PluginInfo {
id: string;
name: string;
description: string;
}
interface Plugin {
init: (router: Router) => Promise<void>;
exit: () => Promise<void>;
info: PluginInfo;
}
请参见下面的"Hello world!"插件示例:
/**
* 初始化插件。
* @param {import('express').Router} router Express 路由器
* @returns {Promise<any>} Promise 在插件初始化时解析
*/
async function init(router) {
// 在这里进行初始化...
router.get('/foo', req, res, function () {
res.send('bar');
});
console.log('Example plugin loaded!');
return Promise.resolve();
}
async function exit() {
// 在这里进行一些清理...
return Promise.resolve();
}
module.exports = {
init,
exit,
info: {
id: 'example',
name: 'Example',
description: 'My cool plugin!',
},
};
#
目录
您可以通过以下方式之一(按优先级顺序)从 plugins 目录中的子目录加载插件:
- 一个
package.json文件,其中包含在 "main" 字段中指向可执行文件的路径。 - CommonJS 模块的
index.js文件。 - ES 模块的
index.mjs文件。
结果文件必须导出一个 init 函数和一个 info 对象,具有与单个文件相同的要求。
目录插件示例(带有 index.js 文件):https://github.com/SillyTavern/SillyTavern-DiscordRichPresence-Server
#
捆绑
最好使用捆绑器(如 Webpack 或 Browserify),它将所有需求打包到一个文件中。确保将 "Node" 设置为构建目标。
使用 Webpack 和 TypeScript 的插件模板仓库:https://github.com/SillyTavern/Plugin-WebpackTemplate