Skip to content

Capabilities & read-only contract ​

The host settings page has to know without starting the engine: does this plugin have a voice list? Does it support voice cloning / voice removal / native speed?


How to declare (two equivalent ways; the host takes the union) ​

json
{
  "capabilities": {
    "voices": true,
    "voice_clone": true,
    "voice_remove": true,
    "speed": false
  }
}
KeyMeaningEquivalent class attribute / method
voicesProvides a voice list (the settings page shows the "Voice" dropdown)Override list_voices()
voice_cloneSupports registering cloned voices (the settings page shows the "Register cloned voice" panel, including recording reference audio inside the app)supports_voice_clone = True
voice_removeSupports deleting registered voices (a "Delete voice" button appears next to kind="registered" voices only)Override remove_voice()
speedNative speed support (duration prediction inside the model, better quality)supports_speed = True

Option 2: class attributes / method overrides ​

python
class MyTTS(BaseTTSProvider):
    supports_voice_clone = True    # supports voice cloning
    supports_speed = True          # native speed

    def list_voices(self): ...     # has a voice list
    def remove_voice(self, name): ...

Read-only query contract (mandatory) ​

When querying capabilities the host never creates a plugin instance, let alone starts your local service.

The host reads from two sources only:

  1. capabilities in mod.json;
  2. your class attributes (it only imports the module and does not call __init__ / initialize).

Two hard requirements follow:

  1. Capabilities must be readable at class level. Assigning them only inside __init__ / initialize → the host cannot see them while no instance exists. (When the host already has an instance it prefers instance attributes, but you must not rely on that.) 👉 Conclusion: write supports_voice_clone / supports_speed in the class body, or declare them in mod.json. voices / voice_remove check whether the method is overridden — an instance attribute cannot override a method.

  2. No read-only method may start a service: list_voices(), check_ready(), and any get_* / status query. When the data is not ready, return an empty list / (False, code, msg) and let the host treat that as "not ready".

Where the host probes read-only ​

  • Opening the settings page / switching tabs
  • Looking at model card status
  • Reading the voice list, checking "supports voice cloning / deletion"
  • Restoring the previously active engine (set_active_provider()) — the active engine is only a config change: no preheat, no load

⚠️ Counter-example (a real bug): putting _start_server() inside initialize(). A user who "only opens the settings page or switches to that engine tab" waits seconds for nothing and burns several GB of VRAM. See Local-service engine contract.


Reference implementation ​

extensions/workshop_common_qwen3_tts (writes capabilities and the class attributes in both places, and none of its read-only paths starts a service).


TransBox — empowering borderless cross-language communication for everyone