Skip to content

Compatibility & version gates ​

target_app_version (required since 0.2), the naming migration table, deprecated types, and the min_app_version rules. Read this page before touching an old plugin.


target_app_version: the adaptation gate (required since 0.2.0) ​

It answers one question for the host: which client generation was this plugin written for? Missing = unknown = incompatible.

json
{ "target_app_version": "0.2" }
Plugin sourceMust declare?When missing
Engine built-ins (is_builtin)NoAlways compatible
extensions/ shipped with the installer (bundled)NoNot subject to this gate
Your own plugins / Steam Workshop / Web Plugin HubYesJudged incompatible and refused outright

Accepted values: 0.2 / 0.2.0 / 0.2.x / >=0.2 / ^0.2 (the rule: it starts with 0.2).

The legacy aliases target_version / host_api are still accepted, but do not use them — write target_app_version.

It is enforced at three gates ​

StageBehaviourLog
Scan / registrationNever enters the plugin list (users think "it isn't installed")[registry] 拒绝识别外部插件 <id>: 缺少 target_app_version 字段(未适配 0.2.0),判定版本不匹配
Instance creationReturns None; enabling / selecting as engine fails[registry] 拒绝加载 <id>: 缺少 target_app_version 或版本不匹配
Hub installThrows InstallError; the package never lands on disk插件 <id> 未声明 target_app_version 字段(未适配 0.2.0 版本),直接判定版本不匹配,已拒绝安装

Why it is this strict ​

A 0.1.x plugin on 0.2.0 does not just "misbehave slightly" — it breaks outright: the SPI was renamed (camelCase → snake_case), runtimes are now host-provided, and config_schema.type spellings were tightened. Refusing before load/install beats letting users stare at a traceback.

Migrating an old plugin (start with this one line) ​

  1. Add "target_app_version": "0.2" to mod.json;
  2. Follow Naming migration and Deprecation and migration to switch to snake_case;
  3. If you depend on a runtime, switch to requires_runtime + host.runtime_dir();
  4. Verify locally: no more 拒绝加载 lines in the log, and the settings page can select your plugin as the engine.

How the two version fields divide the work ​

FieldThe question it answersDefaultWhen omitted
target_app_versionWhich client generation you adapted tononeRefused (must declare 0.2)
min_app_versionThe lowest client version you require1.0.0No restriction

In practice write both: target_app_version marks the generation, and add min_app_version once you actually use a new API.


Naming migration (camelCase → snake_case) ​

Old spellingCanonical nameStatus
host.feedDirectCaptionfeed_direct_captionBoth names coexist for ≥ 1 minor version
host.registerPluginHotkeyregister_plugin_hotkeySame
host.unregisterPluginHotkeysunregister_plugin_hotkeysSame
host.getPluginHotkeysget_plugin_hotkeysSame
camelCase config APIs such as host.getPluginConfigget_plugin_config / set_plugin_config_value / save_plugin_configSame
host.getRecentConversationget_recent_conversationSame
translate(..., source=) reaching straight into the layer belowAdapted inside the implementationCommunity Hunyuan already fixed

New code uses the snake_case names only.


Deprecation and migration ​

Current stateCanonicalMigration
type: middleware + action_*type: toolChange the manifest metadata (tools / text sources should not hang under middleware)
type: audio_filter—Deprecated; the host does not recognise it
type: bundle—Deprecated; the host does not recognise it
Undocumented methods on the bridge—Always treat them as unstable; use the Host SPI instead

Glossary format: there is only one form, an array of objects (src / tgt / src_lang / tgt_lang). Flat dictionaries, tgt as an object/array, language-pair grouping, and terms.txt / tsv all load as an empty table — stop teaching those formats. See glossary.


The min_app_version gate ​

  • The default value 1.0.0 is treated as "no restriction" (it is not taken as a real lower bound). "" / "0" / "0.0.0" are likewise treated as no restriction.
  • When a real lower bound is declared, the host compares it before creating the instance: current app version < min_app_version → loading is refused and a line is left in the log ([registry] 拒绝加载 <id>: 需要应用版本 >= x.y.z,当前 a.b.c).
  • Therefore: local loading may omit it; when publishing to the Plugin Hub version is mandatory, while min_app_version should only be written when you actually use a new API.

Suggested lower bounds ​

What you usedSuggestion
Basic Providers / data pluginsCan be omitted (= no restriction)
Outbound events handle_host_event, feed_caption>= 0.3.0 (go by the version that actually shipped)
Model artifacts model_artifactsSee the change notes for the corresponding version
requires_plugins / requires_runtimeSee the change notes for the corresponding version

Reserved id segments ​

The first segment of a plugin id (the author segment) must not use a reserved name:

text
transbox  official  builtin  community  example  workshop
steam     system    admin    root       support  web  test  tbmod

The server rejects them with reserved_id; local loading is not restricted, but follow the rule anyway, otherwise publishing will always fail.

Recommended format: <your name>.<type>.<name>, for example myteam.mt.deeplx.


Version number rules ​

  • version in mod.json: a semantic x.y.z version.
  • When publishing to the Plugin Hub: mandatory, and it must be higher than the highest online version (otherwise 409 / a prompt to submit a new version).
  • Local client loading may omit it (defaults to 1.0.0).
  • The consuming side decides whether an update exists from "installed receipt version vs the online latest".

TransBox — empowering borderless cross-language communication for everyone