Plugin Capability Declarations
capabilities are the contract between a plugin and Ting Reader. They describe which entries a plugin exposes, who calls them, which runtime function is invoked, what UI should be shown, and which permissions must accompany the feature.
Where Capabilities Are Declared
Declare capabilities in the capabilities array of plugin.yml or plugin.yaml. Each item needs at least id and kind. If invoke is omitted, the backend uses the capability id as the runtime method name.
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| Field | Description |
|---|---|
| id | Unique capability ID inside the plugin, such as metadata.search or assistant.panel. |
| kind | Capability type. This determines how the system discovers and invokes it. |
| invoke | Runtime function name. JavaScript maps this to globalThis[invoke]; WASM and Native runtimes dispatch through their exported entry points. |
| title / label | User-facing entry name. Use a string or a localized { zh, en } object. |
| icon | Client entry icon. UI plugins can use lucide names such as message-circle, or an emoji. |
| priority | Sort order within the same slot. Smaller numbers appear first. |
| contexts | Applicable contexts, such as global, book, reader, and chapter. |
Common Capability Kinds
| kind | Purpose | Common fields |
|---|---|---|
| metadata_provider | Search and scrape book or audiobook metadata. | auto_scrape, search_fields, result_fields, result_field_labels |
| format_handler | Detect formats, produce playback URLs, decrypt streams, and read/write media metadata. | extensions or matches.extensions |
| content_processor | Probe documents, list sections, read chunks, paginate, and render pages. | operations, extensions |
| ui_extension / client_extension | Client buttons, panels, settings forms, or Web UI. | slot, title, icon, render, contexts |
| http_route | Plugin HTTP routes such as RSS, callbacks, and public feeds. | route.method, route.path, route.auth |
| tool_provider | Expose tools to AI assistants, clients, or other plugins. | tools[].name, tools[].description |
| plugin_store | Provide a configurable plugin source. | Usually returns { plugins: [...] } |
| task_handler | Receive custom background tasks. | task_types |
| event_handler | Subscribe to system events. | events; use * to subscribe to all events |
capabilities only declare how a plugin can be called. Reading books, progress, media, cache, files, or network resources still requires matching permissions.UI Entries, Icons, and Menus
For ui_extension, the slot decides where the entry appears. The Web client reads title, icon, priority, and render to build entry menus. global.floating_action appears in the bottom-right plugin entry menu.
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 | Location |
|---|---|
| global.floating_action | Global bottom-right plugin entry menu. |
| global.panel | Global plugin panel entry; also used as a fallback when no floating action exists. |
| settings.section | Plugin settings area. |
| book.detail_action | Book detail action entry. |
| reader.toolbar_action | Reader toolbar action. |
| reader.side_panel | Reader side panel. |
| reader.document_viewer | Document reader extension. |
| render.mode | Description |
|---|---|
| web_container | Loads an HTML entry from ui/ or assets/; the plugin UI talks to the host with postMessage. |
| schema | The client renders a simple form from schema. |
| builtin | Uses a host-provided built-in component, such as the document reader. |
| action | Invokes the capability directly when the entry is clicked. |
For icon, prefer lucide icon names such as message-circle, messages-square, or book-open, or use an emoji. The Web client resolves lucide names first and falls back to text rendering. Flutter first matches the Lucide icon catalog, then falls back to common Material mappings. Image icons support object syntax; Web supports http/https, data:image/..., and / paths, while Flutter supports http/https and assets/.
web_container render.entry is loaded through the plugin asset endpoint. Put static assets under ui/ or assets/, and reference CSS, JS, and images with relative paths. External links can be ordinary <a target="_blank" rel="noopener noreferrer">; do not depend on the return value of window.open() to decide whether the browser opened successfully.
Match Capabilities with Permissions
| Plugin behavior | Common permissions |
|---|---|
| Read books and libraries | books_read |
| Read chapters | chapters_read |
| Read recent playback progress | progress_read |
| Get playback URLs | media_read_url or media_read |
| Store plugin cache | cache_read, cache_write |
| Create or update playlists | playlists_read, playlists_write |
| Call external APIs | network_access; prefer a concrete domain |
| Write metadata or create tasks | metadata_write, task_create; usually requires admin context |
When a permission is missing, HostGateway rejects the call with a permission error. During development, start with minimal permissions and add only what the feature actually needs.