插件能力声明

capabilities 是插件和 Ting Reader 之间的契约:它声明插件提供哪些入口、由谁调用、调用哪个函数、需要显示什么 UI,以及相关权限应该如何配套。

能力声明写在哪里

插件在 plugin.ymlplugin.yamlcapabilities 数组中声明能力。每一项至少需要 idkind;如果省略 invoke,后端会默认使用 capability 自己的 id 作为运行时方法名。

capabilities:
  - id: assistant.panel
    kind: ui_extension
    invoke: openAssistant
    slot: global.floating_action
    title:
      zh: 书单助手
      en: Booklist Assistant
    icon: message-circle
    priority: 20
    contexts: [global, book, reader]
    render:
      mode: web_container
      entry: ui/assistant.html

  - id: metadata.search
    kind: metadata_provider
    invoke: search
    auto_scrape: true
    search_fields:
      - key: title
        label: { zh: 书名, en: Title }
        required: true
        default_from: book.title
    result_fields:
      - key: title
        label: { zh: 书名, en: Title }
      - key: author
        label: { zh: 作者, en: Author }
      - key: cover_url
        label: { zh: 封面, en: Cover }

  - id: assistant.tools
    kind: tool_provider
    invoke: invokeTool
    tools:
      - name: books.recommend
        description: Recommend books from the current user's library

permissions:
  - type: books_read
  - type: progress_read
  - type: network_access
    value: api.example.com
字段说明
id插件内唯一能力 ID,例如 metadata.searchassistant.panel
kind能力类型,决定系统发现和调用这项能力的方式。
invoke运行时函数名。JavaScript 对应 globalThis[invoke],WASM/Native 对应导出的调用分发。
title / label面向用户的入口名,支持字符串或 { zh, en }
icon客户端入口图标,UI 插件可写 lucide 名称如 message-circle,也可以写 emoji。
priority同一 slot 下的排序,数字越小越靠前。
contexts入口适用上下文,例如 globalbookreaderchapter

常用 kind

kind用途常见字段
metadata_provider搜索和刮削书籍、有声书元数据。auto_scrapesearch_fieldsresult_fieldsresult_field_labels
format_handler格式识别、播放 URL、解密、元数据读写。extensionsmatches.extensions
content_processor文档探测、章节、片段、分页和渲染。operationsextensions
ui_extension / client_extension客户端按钮、面板、设置表单或 Web UI。slottitleiconrendercontexts
http_route插件 HTTP 路由,例如 RSS、回调、公开 feed。route.methodroute.pathroute.auth
tool_provider向 AI 助手、客户端或其他插件暴露工具。tools[].nametools[].description
plugin_store提供可配置插件源。通常返回 { plugins: [...] }
task_handler接收插件自定义后台任务。task_types
event_handler订阅系统事件。events,可用 * 订阅全部事件
capabilities 只声明插件能被怎样调用;读取书籍、进度、媒体、缓存、文件或发起网络请求仍必须在 permissions 中声明对应权限。

UI 入口、图标和菜单

ui_extensionslot 决定入口出现在哪里。Web 前端会读取 titleiconpriorityrender 来生成入口菜单;global.floating_action 会出现在右下角插件入口菜单中。

capabilities:
  - id: assistant.panel
    kind: ui_extension
    slot: global.floating_action
    title: { zh: 书单助手, en: Booklist Assistant }
    icon: message-circle
    render:
      mode: web_container
      entry: ui/assistant.html

  - id: quick.note
    kind: ui_extension
    slot: global.floating_action
    title: { zh: 快速笔记, en: Quick Note }
    icon: "📝"
    render: action
slot显示位置
global.floating_action全局右下角插件入口菜单。
global.panel全局插件面板入口,可作为 floating action 的 fallback。
settings.section设置页插件配置区域。
book.detail_action书籍详情页动作入口。
reader.toolbar_action阅读器工具栏动作。
reader.side_panel阅读器侧边面板。
reader.document_viewer文档阅读器扩展。
render.mode说明
web_container加载 ui/assets/ 下的 HTML 入口,插件 UI 通过 postMessage 与宿主通信。
schema由客户端根据 schema 渲染简单表单。
builtin调用宿主内置组件,例如文档阅读器。
action点击入口后直接调用 capability。

icon 推荐使用 lucide 图标名(例如 message-circlemessages-squarebook-open)或一个 emoji。Web 前端会优先按 lucide 名称解析,无法解析时按文本图标显示;Flutter 会优先匹配 Lucide 图标 catalog,找不到时再按常见名称回退到 Material 图标。图片图标支持对象写法,Web 支持 http/httpsdata:image/.../ 路径,Flutter 支持 http/httpsassets/

web_containerrender.entry 会通过插件资产接口加载。静态资源建议放在 ui/assets/ 下,并使用相对路径引用 CSS、JS 和图片。外部链接写普通 <a target="_blank" rel="noopener noreferrer"> 即可,插件不要依赖 window.open() 返回值判断是否打开成功。

能力与权限要配套

插件要做什么常见权限
读取书籍、存储库列表books_read
读取章节chapters_read
读取最近播放进度progress_read
获取播放地址media_read_urlmedia_read
保存插件缓存cache_readcache_write
创建或修改播放列表playlists_readplaylists_write
访问外部 APInetwork_access,建议填写具体域名
写元数据或创建任务metadata_writetask_create,通常需要管理员上下文

权限缺失时,HostGateway 会拒绝调用并返回权限错误。开发时建议先最小化权限,只有实际需要时再增加。