Wox Python 插件 SDK 完整开发指南:从 Plugin 基类到动态设置与查询精化
【免费下载链接】WoxA cross-platform launcher that simply works项目地址: https://gitcode.com/gh_mirrors/wo/Wox
本篇指南以 Wox 官方 Python 插件 SDK 参考文档(.agents/skills/wox-plugin-creator/references/sdk_python.md)为核心骨架,结合仓库中wox.plugin.python/src/wox_plugin/的源码实现,系统讲解如何在 Wox 中开发 Python 插件:从环境准备、安装wox-plugin包、实现Plugin基类与数据模型,到熟练使用全部 Public API、编写可云同步的设置、配置 QueryRequirements、实现动态设置与静态 HTML 预览。读完本文,你将能独立完成一个结构规范、功能完整的 Wox Python 插件,并理解每个 API 背后的调用语义与版本约束。
Wox 要求Python 3.10 或更高版本。这一约束在仓库源码中有双重印证:wox.plugin.python/pyproject.toml中声明requires-python = ">=3.10",而 Python 宿主实现 中同样定义了minimumPythonVersion = v3.10.0,并在解析到低于该版本的解释器时直接报错,保证 API 解析器与宿主进程使用同一套版本规则。
环境准备与 SDK 安装
安装 wox-plugin 包
在插件项目目录中执行:
uv add wox-plugin该命令通过uv将wox-plugin加入项目依赖。包内部组织清晰:顶层__init__.py统一导出Plugin、Query、QueryResponse、Result、Context、PluginInitParams以及WoxImage、WoxPreview、LogLevel、设置辅助函数等全部公开符号(见 SDK 包导出),因此from wox_plugin import ...一条导入即可覆盖绝大多数场景。
插件元数据 plugin.json
插件根目录需要plugin.json声明元数据,其中Runtime必须为"python"、Entry指向插件入口脚本(如main.py)。若插件返回QueryResponse,则MinWoxVersion必须声明为>= 2.0.4(参见 SDK 元数据示例)。
Plugin 基类与最小可运行插件
所有 Wox Python 插件的入口都实现Plugin协议(协议定义),至少包含两个异步方法:
from wox_plugin import Plugin, Query, QueryResponse, Result, Context, PluginInitParams class MyPlugin(Plugin): async def init(self, ctx: Context, params: PluginInitParams) -> None: self.api = params.api async def query(self, ctx: Context, query: Query) -> QueryResponse: return QueryResponse(results=[])init(ctx, params):插件加载时调用一次,应尽快返回。params.api是PublicAPI实例(类型见 PublicAPI 协议),params.plugin_directory是插件目录绝对路径,可用于加载配置文件与资源。query(ctx, query):用户输入命中插件时调用。返回QueryResponse(要求MinWoxVersion >= 2.0.4)或直接返回List[Result](兼容旧版本 Wox 的弃用路径)。
文件末尾实例化单例:
plugin = MyPlugin()返回值的版本语义
从源码注释(Plugin 协议兼容性说明)可以确认:直接返回List[Result]仍被宿主接受,但属于弃用路径;只有QueryResponse能把结果、refinements 与 layout 提示放在同一个载荷中一并上送。因此新插件应统一使用QueryResponse。
查询作用域布局(query-scoped layout)
QueryResponse.layout是查询级的布局声明,包含result_preview_width_ratio与grid_layout两个可选字段(QueryLayout 实现):
from wox_plugin import QueryResponse, QueryLayout, QueryGridLayout return QueryResponse( results=results, layout=QueryLayout( result_preview_width_ratio=0.6, grid_layout=QueryGridLayout(columns=3, image_width=200, image_height=200, show_title=True), ), )QueryGridLayout还支持item_padding、item_margin、aspect_ratio、commands等字段(QueryGridLayout 实现)。旧版的resultPreviewWidthRatio与gridLayout元数据特性已被弃用,原因正如源码注释所指:它们只能描述静态的插件或命令默认值,无法像QueryResponse.layout一样按每次查询动态决策。
核心数据模型
Query
class Query: type: str # "input" 或 "selection" raw_query: str trigger_keyword: str command: str search: str refinements: dict[str, str] # 已选中的 refinement 值type对应QueryType.INPUT(在搜索框输入)或QueryType.SELECTION(在外部应用选中文本/文件后唤起 Wox),见 QueryType 定义。trigger_keyword是插件触发词,command是已注册的子命令关键字,search是去除触发词与命令后的实际搜索文本。refinements保存用户在查询作用域精化控件上的选择。
QueryRefinement
class QueryRefinement: id: str title: str type: QueryRefinementType # singleSelect | multiSelect | toggle | sort hotkey: str # macOS 上为 cmd+t,Windows/Linux 上为 ctrl+t options: list[QueryRefinementOption] default_value: list[str] = [] persist: bool = Falsetype为QueryRefinementType枚举(SINGLE_SELECT/MULTI_SELECT/TOGGLE/SORT),见 query_response.py。hotkey必须是真实的平台组合键:macOS 用cmd+<key>,Windows/Linux 用ctrl+<key>。代码中应检测sys.platform == "darwin"后输出对应字符串,切勿直接写死字面量ctrl/cmd+t。- 插件通过
QueryResponse.refinements返回精化控件,并在下一次查询时从query.refinements读取已选值(详见references/refinements.md)。
Result
class Result: title: str # 支持 "i18n:key" 前缀自动翻译 icon: WoxImage sub_title: str = "" # 支持 "i18n:key" 前缀 actions: List[ResultAction] = [] score: float = 0.0 context_data: Any = None源码中的 Result 模型 还提供了更多字段:id(跨更新追踪结果)、preview(详情面板预览)、group/group_score(结果分组与组排序)、tails(文本/图片尾巴元素)、drag_data(原生文件拖拽)等。score决定排序,数值越高越靠前。
ResultAction支持EXECUTE(立即执行)与FORM(先展示表单再提交,回调收到FormActionContext.values)两种类型,并可用prevent_hide_after_action=True保持 Wox 窗口在执行动作后不隐藏,详见 ResultAction 模型。
WoxImage
class WoxImage: @classmethod def new_emoji(cls, char: str) -> "WoxImage" @classmethod def new_absolute(cls, path: str) -> "WoxImage" @classmethod def new_relative(cls, path: str) -> "WoxImage"WoxImage 实现 支持多种图片类型:ABSOLUTE、RELATIVE(相对插件目录)、BASE64(完整 data URI)、SVG(内联 SVG 标记)、EMOJI、URL、THEME(内置主题图标,随明暗主题自适应)、FILE_ICON(按文件扩展名取系统图标)。对应工厂方法还包括new_base64()、new_svg()、new_url()、new_theme()等。
Action 图标应使用可适配主题的 SVG(svg:或使用var(--wox-theme-icon-color)的内联标记),而不是 emoji,详见references/icons.md。
Public API 方法全览
所有方法均为异步且需要ctx。以下是 SDK 参考文档列出的核心 API,按类别整理:
通用控制
| 方法 | 作用 |
|---|---|
change_query(ctx, query: PlainQuery) | 更新搜索栏内容(支持ChangeQueryParam指定查询类型与文本/选区) |
hide_app(ctx) | 隐藏 Wox |
show_app(ctx) | 显示 Wox |
notify(ctx, message) | 显示系统通知(支持 i18n key) |
log(ctx, level, msg) | 写日志,level取LogLevel枚举(INFO/ERROR/DEBUG/WARNING) |
copy(ctx, params: CopyParams) | 复制文本或图片到剪贴板 |
is_visible(ctx) | 检查 Wox 窗口是否可见 |
缓存
插件需要磁盘缓存时,优先使用get_cache_folder,不要自创目录:
get_cache_folder(ctx):返回~/.wox/cache/plugins/<plugin-id>/。Wox 会在需要时自动创建,并在插件卸载时删除。- 在
init()中调用一次并保存路径,把下载文件、缩略图、搜索结果等写入其下。 - 不要在插件文件旁、用户数据目录下或硬编码文件夹名下自行发明
cache/、tmp/、downloads/目录。 - 用户偏好与收藏属于设置而非缓存,请使用
get_setting/set_setting。
该 API 在 PublicAPI 协议 中有完整的路径语义注释。
设置
插件设置应优先使用以下 API——这些值可以通过 Wox 云同步跨设备同步,不要把普通设置持久化到本地文件或自定义存储中:
get_setting(ctx, key):读取设置值(未设置时返回默认值)。save_setting(ctx, key, value, is_platform_specific):保存设置。普通插件设置可参与云同步;对于本地路径、可执行文件路径、shell 命令、热键、浏览器配置、应用路径、系统集成等仅限当前平台的值,is_platform_specific传True。on_setting_changed(ctx, callback):注册设置变更回调,回调签名(ctx, key, new_value)。on_get_dynamic_setting(ctx, callback):为dynamic类型设置提供运行时生成的设置定义,回调返回PluginSettingDefinitionItem。
save_setting在源码中已被标注为 Deprecated(api.py 中的说明),新插件在MinWoxVersion >= 2.4.0时应改用set_setting(ctx, SetSettingOption(...)),后者通过platform_specific与is_local两个布尔字段显式控制跨平台与设备本地行为(见 SetSettingOption 实现)。
UI 实时更新
update_result(ctx, result: UpdatableResult):实时更新结果(用于动作处理中的长任务进度展示)。push_results(ctx, query, results):向当前查询追加结果(适合流式返回、分批加载)。refresh_query(ctx, param):以现有文本重新执行查询(RefreshQueryParam.preserve_selected_index控制是否保持选中项)。get_updatable_result(ctx, result_id):获取某结果的当前 UI 状态,结果已不可见时返回None。
AI 与国际化
ai_chat_stream(ctx, model, convs, options, callback):流式获取 LLM 响应。model为AIModel(name=..., provider=...),convs为Conversation列表(可用user_message()/assistant_message()便捷构造),回调接收ChatStreamData(状态为STREAMING/FINISHED/ERROR)。get_translation(ctx, key):获取原始翻译字符串。注意返回的是原始字符串,参数替换需自行用 f-string 或.format()完成。
设置编写要点
- 插件设置一律走
get_setting/save_setting/on_setting_changed,以便参与 Wox 云同步;不要让用户期望"换设备还在"的值落入本地文件。 - 缓存文件放在
get_cache_folder(ctx)下,不要在插件目录或用户数据树下自造缓存目录。 - Python SDK 内置以下设置构建辅助函数(定义见 setting.py):
create_textbox_setting(key, label, default_value="", tooltip=""):单行文本框设置。create_checkbox_setting(key, label, default_value="false", tooltip=""):布尔开关("true"为选中)。create_label_setting(content, tooltip=""):只读说明文字。
- 目前没有内置
create_select_setting()辅助函数。 - 对于
select、table、校验器、dynamic等高级设置,需要直接构造PluginSettingDefinitionItem与对应的值对象(如PluginSettingValueTable、PluginSettingValueTableColumn、PluginSettingValueTableGroup),或手动输出期望的 JSON 结构。设置类型枚举见 PluginSettingDefinitionType(head/textbox/checkbox/select/label/newline/table/dynamic)。 - 精确的
plugin.json与校验器结构请阅读references/plugin_json_schema.md;可直接复制的高级设置示例见references/settings_patterns.md。 - 运行时
save_setting(ctx, key, value, is_platform_specific)调用必须与设置元数据保持一致:如果对应SettingDefinitions条目声明了IsPlatformSpecific: true,不要对动态保存的设置硬编码False。 DisabledInPlatforms只控制设置在哪些平台被禁用,不会隔离云同步的值。- 当查询依赖 API Key 等设置时,在
plugin.json中使用静态QueryRequirements。Wox 会在调用query()之前拦截查询,仅显示内置的query_requirement_settings配置预览。 - 不存在运行时的
register_query_requirementsAPI,查询需求一律在元数据中声明。
QueryRequirements 数据类与元数据示例
from dataclasses import dataclass, field @dataclass class PluginQueryRequirement: setting_key: str validators: list[dict] = field(default_factory=list) message: str = "" @dataclass class PluginQueryRequirements: any_query: list[PluginQueryRequirement] = field(default_factory=list) query_without_command: list[PluginQueryRequirement] = field(default_factory=list) query_with_command: dict[str, list[PluginQueryRequirement]] = field(default_factory=dict)其语义在 PluginQueryRequirements 源码 中有明确注释:any_query作用于所有查询,query_without_command仅作用于无子命令的查询,query_with_command按命令关键字分别配置。to_dict()会转换成plugin.json使用的 PascalCase 字段名。
元数据示例:
{ "SettingDefinitions": [ { "Type": "textbox", "Value": { "Key": "accessKey", "Label": "i18n:access_key", "DefaultValue": "", "Validators": [{ "Type": "not_empty", "Value": {} }] } } ], "QueryRequirements": { "AnyQuery": [ { "SettingKey": "accessKey", "Message": "i18n:access_key_required" } ], "QueryWithoutCommand": [], "QueryWithCommand": {} } }校验器类型除not_empty外,仓库setting/validator/目录还提供is_number、is_url、unique等实现可供参考。
动态设置(Dynamic Setting)示例
动态设置由on_get_dynamic_setting回调在运行时生成定义,适合值取决于当前状态(如预览、可选列表)的场景:
from wox_plugin import ( PluginSettingDefinitionItem, PluginSettingDefinitionType, PluginSettingValueLabel, ) async def _on_get_dynamic_setting(ctx, key): if key == "separator_preview": return PluginSettingDefinitionItem( type=PluginSettingDefinitionType.LABEL, value=PluginSettingValueLabel(content="Preview: 1,234.56"), ) return PluginSettingDefinitionItem( type=PluginSettingDefinitionType.LABEL, value=PluginSettingValueLabel(content="Unknown setting"), )回调在init()中注册:await self.api.on_get_dynamic_setting(ctx, self._on_get_dynamic_setting)。
完整使用示例:带 i18n 格式化的 Hello 插件
from wox_plugin import Plugin, Query, Result, WoxImage class HelloPlugin(Plugin): async def init(self, ctx, params): self.api = params.api async def query(self, ctx, query): # I18n with formatting raw_fmt = await self.api.get_translation(ctx, "hello_format") # "Hello {name}" title = raw_fmt.format(name=query.search) return [Result( title=title, icon=WoxImage.new_emoji("👋"), actions=[] )] plugin = HelloPlugin()注意:get_translation返回的是包含{name}占位符的原始字符串,需用.format()完成替换——这正是 SDK 参考中强调的要点。
静态 HTML 预览(WEBVIEW)
预览结果时,使用WoxPreviewType.WEBVIEW并传入 JSON 编码的html字段即可,无需 HTTP 服务器或临时 HTML 文件,也不存在独立的html预览类型:
import json from wox_plugin import WoxPreview, WoxPreviewType preview = WoxPreview( preview_type=WoxPreviewType.WEBVIEW, preview_data=json.dumps({ "html": '<!doctype html><html><body><h1 style="color:teal">Hello Wox</h1></body></html>' }), ) # Assign preview to Result(preview=preview, ...).html与url二选一。可选 JSON 字段:injectCss、userAgent、cacheDisabled、cacheKey(默认取 URL 或 HTML 内容)。- 内联 HTML 没有相对插件的 base URL:请内联 CSS/图片或使用绝对资源 URL。
- 这是浏览器内容而非经过净化的 Markdown;拼接不可信文本前务必使用
html.escape。
WoxPreview模型还支持MARKDOWN、TEXT、IMAGE、URL、FILE、LIST、REMOTE等类型(WoxPreviewType 定义),其中LIST可通过WoxPreviewListData展示带图标、副标题与尾巴的结构化行。
结构化查询参数与命令块
- 命令的别名配置在
Commands[].Aliases,后缀模板配置在Commands[].QueryHint,完整的ChangeQuery实例与 SDK 用法详见.agents/skills/wox-plugin-creator/SKILL.md的QueryHint章节。 QueryHint对input查询仍是可选项;不要在QueryText中嵌入标记,也不要从粘贴文本中推断参数边界。
常用参考路径
- SDK 参考文档(本文依据)
- Python SDK 包导出
- PublicAPI 协议与全部方法签名
- Plugin 协议与生命周期
- Result / ResultAction / UpdatableResult 模型
- QueryResponse / Refinement / Layout 模型
- 设置定义模型与辅助函数
- WoxImage 图片模型
- WoxPreview 预览模型
- Python 宿主版本校验
- 配套参考:插件 JSON Schema、设置模式、精化控件、图标规范、i18n
【免费下载链接】WoxA cross-platform launcher that simply works项目地址: https://gitcode.com/gh_mirrors/wo/Wox
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考