tenko-plugin-example
Tenko 扩展插件的示例与起步模板。它演示:
- 用
tenko_api.features.declare声明按群开关、默认状态、限流权重和群等级; - 用
[plugin_config.example]配置插件(Entari 的BasicConfModel); - 用
tenko_api.storage.Store保存带版本号的 JSON 数据,用Model和get_session()使用插件自己的 SQLite 库; - 用
tenko_api.perm的装饰器(@require等)声明命令权限,用 Entari 原生的command.on注册命令。
插件命令 /示例 [备注] 记录你使用命令的次数(JSON)和备注历史(SQLite)。
从模板开始
- 复制本目录作为新项目(在 GitHub 上可以把它放进自己的仓库)。
- 改名:分发名用
tenko-plugin-xxx,模块名用tenko_plugin_xxx。同步修改pyproject.toml的name、[tool.hatch.build.targets.wheel]、src/目录名,以及 入口[project.entry-points."tenko.plugins"]里的<插件 ID> = "<模块>"。 插件 ID 匹配[a-z][a-z0-9_]*,全局唯一,不能和内置插件同名;它是功能开关、 配置节和数据目录的键。 - 换成你自己的信息:
plugin.metadata的author、description,以及pyproject.toml的[project.urls](插件目录靠这里的 GitHub 地址确认仓库归你所有)。示例本身作为真实 插件发布在 PyPI 上,这些地方写的是 Tenko 维护者的信息。 - 不要声明
entari.plugin入口:Entari 会无视 Tenko 的启用状态自动加载它。 - 依赖只写
tenko-api的兼容范围(预览期为>=0.4,<0.5)和插件自己的依赖, 不要依赖tenko本体,也不要用==锁死依赖版本。
开发与测试
uv sync # 创建环境,开发依赖里包含从 Git 安装的 Tenko 宿主(发布后请固定到版本标签)
uv run pytest -q
uv run ruff check .
tests/conftest.py 用真实的宿主加载插件:按 tenko.plugins 入口发现、启用、传入配置,
然后直接调用命令处理函数。不需要启动 Tenko,也不需要连接聊天平台。
写法要点:
- 宿主能力一律从
tenko_api导入,不要导入tenko.*内部模块。 declare(...)必须在插件模块导入期间调用(与plugin.metadata(...)放在一起)。data_dir()和Store只能在插件自己的模块里使用,数据位于.tenko/plugin-data/<插件 ID>/。 数据结构变化时提高Store的版本号并提供migrate,宿主会先把旧文件备份为<名称>.json.bak-v<旧版本>;插件被降级、读到更新版本的文件时会报错而不是覆盖。Model子类在插件模块导入期间定义,表建在data.db;启动时自动建表和增加可空列, 删除或修改列会被拒绝,需要时写官方的register_custom_migration脚本。测试里要像宿主 那样先加载数据库插件、再加载插件、最后初始化并迁移(见tests/conftest.py)。 版本变化后宿主会先备份库到backups/。- 命令权限用
tenko_api.perm的装饰器声明,不要在函数体里重复检查;装饰器在@command.on(...)之上或之下都生效。因为装饰器由 Entari 调度,测试里直接调用callable_target不会经过它们,应检查登记的要求(见tests/test_plugin.py), 或像tests/tenko里那样走真实分发。 - Entari 对标准 dataclass 配置模型不做类型校验,需要时在
__post_init__里检查。
在 Tenko 里启用
- 在运行 Tenko 的环境里安装插件:
uv pip install tenko-plugin-xxx(本地调试用uv pip install -e /path/to/plugin)。 - 如有配置,在
config/tenko.toml里添加[plugin_config.<插件 ID>],见仓库中config/tenko.toml.example末尾的说明。运行中的 Tenko 只认启动时读到的配置,改了配置 要重启。 - 打开 WebUI 的插件页,启用该插件(带“扩展”标记)。扩展插件默认关闭,启用后写入
.tenko/plugins/state.json并直接加载。 - 本示例定义了数据库模型,运行中加载会被拒绝,面板会提示重启(聊天里的
/重启或重新 运行进程)。没有数据库模型的插件不需要这一步。
插件可能在 Tenko 运行中被加载,这时启动、就绪等生命周期事件已经过去,初始化不要只放在 这些事件里。
之后可以在 WebUI 开关页或用 /开启、/关闭 按群控制,插件命令与内置命令走同一套
维护模式、功能开关和限流。
发布
发布到 PyPI(推荐,使用 Trusted Publishing,不保存 token)
-
在 PyPI 上添加 pending publisher:项目名填你的分发名,所有者和仓库填你的 GitHub 仓库,工作流填
publish.yml,环境填pypi。 -
在 GitHub 仓库设置里创建名为
pypi的 Environment。 -
把
pyproject.toml的版本改为X.Y.Z,提交后打标签并推送:git tag vX.Y.Z && git push origin vX.Y.Z
.github/workflows/publish.yml会检查标签与版本一致、构建并发布。
只用 GitHub:不发布到 PyPI 时,使用者可以直接
uv pip install "tenko-plugin-xxx @ git+https://github.com/<你>/<仓库>@<标签或提交>",
请固定到标签或提交哈希。
收录到插件目录
发布到 PyPI(或打好 Git 标签)后,在 tenko-registry
用投稿表单填写来源即可。插件 ID、名称、简介、作者、许可证和兼容范围都由目录的 CI 从
pyproject.toml 和 plugin.metadata(...) 读取,之后的新版本也会自动追加。
图标可选:在 plugin.metadata(icon="https://…") 里给出图片地址,或在投稿表单里上传。要求
透明背景的单色图形(PNG 或 WebP,不接受 JPEG、SVG 和动图),短边至少 64 px;目录会裁成
正方形、缩放到 128×128 PNG 并自行托管,Tenko 只显示目录托管的图标。
兼容性
tenko-api 遵循语义化版本(1.0 之前为预览,接口可能调整)。插件声明的范围由宿主在
加载前检查:宿主提供的 tenko-api 不在范围内时,插件不加载,日志说明原因。注意 uv pip install
遇到不兼容的范围不会报错,而是把环境里的 tenko-api 换成插件要的版本,所以不能靠安装结果判断兼容性。
Metadata
Release files for tenko-plugin-example 0.3.0
For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.
Source distribution (sdist)
| File | Size | Uploaded | Provenance | |
|---|---|---|---|---|
| tenko_plugin_example-0.3.0.tar.gz | 10.5 kB | With provenance | Details |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Reset |
|---|---|---|---|---|
| tenko_plugin_example-0.3.0-py3-none-any.whl | Python 3 | none | any | Details |
Total release size: 17.3 kB
Release files / tenko_plugin_example-0.3.0.tar.gz
| Download URL | tenko_plugin_example-0.3.0.tar.gz |
|---|---|
| Size | 10.5 kB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
0886a15fe91dcd59fbc88b9b9bbf784acd103ddeefe998b3654f168d23d750a7
|
|
BLAKE2b-256 checksum How to use checksums |
ef2d4558dc56a4ffc3d335b391787324c1fb1cc6dc21197274dc7c914d3520a3
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
twine/7.0.0 CPython/3.13.16
|
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
PyPI Publish Attestation
PyPI verified that this artifact, at this checksum, originated from the publisher listed below.
Signed by GitHub Actions, verified by PyPI on Oct 23, 2026.
Transparency logRelease files / tenko_plugin_example-0.3.0-py3-none-any.whl
| Download URL | tenko_plugin_example-0.3.0-py3-none-any.whl |
|---|---|
| Size | 6.9 kB |
| Tags | Python 3 |
|
SHA-256 checksum How to use checksums |
3034c99d3f595c016b8f2b72b83b077a332e960feafed7107327f999da8f5fa2
|
|
BLAKE2b-256 checksum How to use checksums |
5309896761495025a3138962c2734ca13d0b1319b1fbde1a676538dabc5e7203
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
twine/7.0.0 CPython/3.13.16
|
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
PyPI Publish Attestation
PyPI verified that this artifact, at this checksum, originated from the publisher listed below.
Signed by GitHub Actions, verified by PyPI on Oct 23, 2026.
Transparency logSecurity for tenko-plugin-example 0.3.0
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
Full provenance
All 2 files in this release have been uploaded with provenance metadata.
Attestation for tenko_plugin_example-0.3.0.tar.gz
PyPI Publish Attestation
PyPI verified that this artifact, at this checksum, originated from the publisher listed below.
Signed by GitHub Actions, verified by PyPI on Oct 23, 2026.
Transparency logA note on package security
PyPI is a repository for distributing packages, not a service for auditing them. While third-party security researchers and our staff do their best to detect and remove malicious packages, PyPI cannot guarantee the quality, security or suitability of any given package.
To learn more about protecting yourself from malicious actors, visit our package security documentation.