order | icon |
---|---|
-30 |
server |
These plugins allow adding functionality that is impossible to achieve using UI extensions alone, such as creating new API endpoints or using Node.JS packages that are unavailable in a browser environment.
Plugins are contained in the plugins
directory of SillyTavern and loaded on server startup, but only if enableServerPlugins
is set to true
in the config.yaml
file.
Plugins are not sandboxed, be careful what you install and run!
An executable JavaScript file with ".js" (for CommonJS modules) or ".mjs" (for ES modules) extension containing a module that exports an init
function that accepts an Express router (created specifically for your plugin) as an argument and returns a Promise.
The module should also export an info
object containing the information about the plugin (id
, name
, and description
strings). This will provide the information about the plugin to the loader.
You can register routes via the router that will be registered under the /api/plugins/{id}/{route}
path. For example router.get('/foo')
for plugin example
will produce a route like this: /api/plugins/example/foo
.
A plugin could also optionally export an exit
function that performs clean-up on shutting down the server. It should have no arguments and must return a Promise.
TypeScript contract for plugin exports:
interface PluginInfo {
id: string;
name: string;
description: string;
}
interface Plugin {
init: (router: Router) => Promise<void>;
exit: () => Promise<void>;
info: PluginInfo;
}
See below for a "Hello world!" plugin example:
/**
* Initialize plugin.
* @param {import('express').Router} router Express router
* @returns {Promise<any>} Promise that resolves when plugin is initialized
*/
async function init(router) {
// Do initialization here...
router.get('/foo', req, res, function () {
res.send('bar');
});
console.log('Example plugin loaded!');
return Promise.resolve();
}
async function exit() {
// Do some clean-up here...
return Promise.resolve();
}
module.exports = {
init,
exit,
info: {
id: 'example',
name: 'Example',
description: 'My cool plugin!',
},
};
You can load a plugin from a subdirectory in the plugins
in one of the following ways (in the order of checks):
package.json
file that contains a path to an executable file in the "main" field.index.js
file for CommonJS modules.index.mjs
file for ES modules.
A resulting file must export an init
function and info
object with the same requirements as for individual files.
Example of a directory plugin (with index.js
file): https://github.com/SillyTavern/SillyTavern-DiscordRichPresence-Server
It is preferable to use a bundler (such as Webpack or Browserify) that will package all of the requirements into one file. Make sure to set "Node" as a build target.
Template repository for plugins using Webpack and TypeScript: https://github.com/SillyTavern/Plugin-WebpackTemplate