资讯详情

Wox 单文件 SDK 插件开发指南:一个文件、完整 Public API、常驻宿主进程

📅 2026/9/20 19:32:58 | 华诺云谱 👁 阅读
Wox 单文件 SDK 插件开发指南:一个文件、完整 Public API、常驻宿主进程
Wox 单文件 SDK 插件开发指南一个文件、完整 Public API、常驻宿主进程【免费下载链接】WoxA cross-platform launcher that simply works项目地址: https://gitcode.com/gh_mirrors/wo/Wox单文件 SDK 插件Single-file SDK Plugin是 Wox 提供的一种轻量级插件形态只需一个.py或 CommonJS.js文件无需打包.wox即可获得与普通 SDK 插件完全相同的 Public API同时常驻在 Wox 的 Python / Node.js runtime host 中不为每次 query 重复启动进程。本文基于 Wox 官方开发文档 www/docs/zh/development/plugins/single-file-plugin.md结合仓库源码深入讲解其运行机制、Metadata 规范、热重载行为与商店发布约束帮助你在一个文件与完整 API之间找到最佳平衡点。与其它插件类型的区别Wox 目前存在三种插件形态单文件 SDK 插件恰好处于脚本插件与完整 SDK 插件之间Script Plugin 单文件 每次调用启动进程 stdin/stdout JSON-RPC Single-file SDK Plugin 单文件 常驻 SDK runtime host 完整 Public API SDK Plugin .wox 包 常驻 SDK runtime host 完整 Public API选择依据非常简单需求选择一次性 shell / 命令包装脚本插件只要一个文件但需要 Wox API单文件 SDK 插件需要依赖、资源、TypeScript 或多文件SDK 插件需要强调的是脚本插件不是单文件 SDK 插件的旧版本也不会被废弃。二者各有适用场景——脚本插件适合无状态的一次性命令包装而单文件 SDK 插件则适合不想打包、又想调用 Wox API、还希望复用宿主进程的场景。单文件 SDK 插件的 query/action 复用宿主进程Wox 不会为插件单独创建 Python 或 Node 进程宿主崩溃后的恢复机制继续复用现有的 watchdog 逻辑。从源码看watchdog 每隔 5 秒检查一次共享宿主健康状态hostWatchdogCheckInterval 5 * time.Second连续 3 次重启失败会进入 5 分钟的冷却期防止某个插件反复杀死宿主造成重启风暴详见 wox.core/plugin/host_watchdog.go。快速开始使用 wpm 创建运行wpm create name在模板列表中选择Python 单文件 SDK 插件或Node.js 单文件 SDK 插件。WPM 会直接把文件写入共享目录~/.wox/wox-user/plugins/single-file/Wox.Plugin.Name.py ~/.wox/wox-user/plugins/single-file/Wox.Plugin.Name.js然后打开该文件开始编辑。保存后 Wox 会自动 reload无需重启。这也是 WPM 直接创建 Python SDK 插件的路径。除非你需要额外文件或 pip 依赖否则不必去克隆打包版 Python 模板。相关模板定义与创建流程可见 wox.core/plugin/system/wpm.goplugin_wpm_singlefile_template_python/plugin_wpm_singlefile_template_nodejs。Python 单文件插件Python 文件的 Runtime 是PYTHON。可以直接import wox_plugin使用 SDK 的模型、helper 和全部 Public API该 SDK 包位于仓库 wox.plugin.python/src/wox_plugin# { # Id: com.example.weather, # Name: Weather, # Author: Example, # Version: 1.0.0, # MinWoxVersion: 2.4.2, # Runtime: PYTHON, # Description: Show current weather, # Icon: emoji:️, # TriggerKeywords: [weather], # SupportedOS: [Windows, Linux, Macos] # } from wox_plugin import PluginInitParams, Query, QueryResponse, Result, WoxImage class WeatherPlugin: async def init(self, ctx, params: PluginInitParams): self.api params.api async def query(self, ctx, query: Query): return QueryResponse(results[ Result( titleWeather, iconWoxImage.new_emoji(️), ) ]) plugin WeatherPlugin()Node.js 单文件插件Node.js 文件的 Runtime 是NODEJS。第一版固定为 CommonJS规则如下扩展名必须是.js使用module.exports.plugin导出插件对象通过params.API使用全部 Public API不要import/requirewox-launcher/wox-pluginWoxImage等简单类型使用对象字面量第一版不支持.mjs、ESM、TypeScript、npm 依赖和 SDK npm helper。当前 Node host 会把动态import()编译成require()只有保持 CommonJS 才能复用现有加载逻辑和require.cache热重载机制// { // Id: com.example.weather, // Name: Weather, // Author: Example, // Version: 1.0.0, // MinWoxVersion: 2.4.2, // Runtime: NODEJS, // Description: Show current weather, // Icon: emoji:️, // TriggerKeywords: [weather], // SupportedOS: [Windows, Linux, Macos] // } class WeatherPlugin { async init(ctx, params) { this.api params.API } async query(ctx, query) { return { Results: [{ Title: Weather, Icon: { ImageType: emoji, ImageData: ️ }, Actions: [] }] } } } module.exports.plugin new WeatherPlugin()Metadata文件头部的内联 JSON解析机制Metadata 不是独立文件而是放在文件开头的#或//注释块中的一个 JSON 对象。文件头允许第一行 shebang。从源码看解析器extractInlineCommentHeader会收集文件头部连续的注释行允许空行穿插然后parseInlineMetadataContent使用json.Decoder从第一个{开始解码——这保证了字符串内部的花括号和转义序列不会破坏解析。逻辑见 wox.core/plugin/inline_metadata.go。必填字段单文件 SDK 插件必须显式提供以下字段IdNameVersionMinWoxVersionRuntimeTriggerKeywords可选字段同时支持Author、Description、Icon、Website、Commands、SupportedOS、Features、Glances、SettingDefinitions、QueryRequirements、I18n。自动填充与禁止声明Wox 会把Entry设为当前文件名把Directory设为plugins/single-file。因此文件头不允许声明Entry或Directory——源码中的validateSingleFilePluginMetadata会直接拒绝这两个字段并最终写入metadata.Entry filepath.Base(filePath)、metadata.Directory GetUserSingleFilePluginsDirectory()见 wox.core/plugin/inline_metadata.go。另外MinWoxVersion必须是一个合法 SemVer 版本号加载时会被ensureWoxVersionSupported校验见 wox.core/plugin/manager.go低于当前 Wox 版本的插件无法进入 runtime host。Runtime 必须与后缀匹配Runtime 必须和文件后缀匹配Wox不会猜测或降级文件合法 Runtime.pyPYTHON.jsNODEJS该映射由singleFileRuntimeForPath实现见 wox.core/plugin/single_file.go。在validateSingleFilePluginMetadata中如果声明的 Runtime 与后缀推导结果不一致会直接报错runtime %s does not match file extension %s。不要放进 scripts 目录不要把PYTHON/NODEJS文件放进plugins/scripts/未声明 Runtime 的脚本插件仍按SCRIPT加载如果在 scripts 目录里显式声明了PYTHON/NODEJS加载会被拒绝并提示把文件移到plugins/single-file/。对应实现见ParseScriptMetadata脚本插件声明 Python/Node Runtime 时返回错误move this file to ... single-file ...wox.core/plugin/inline_metadata.go。同时single-file与scripts这两个目录被标记为保留用户插件目录不会被当作打包插件目录扫描见 wox.core/plugin/single_file.go。保存后自动 reload防抖与触发流程保存文件后Wox 大约经过500ms 防抖后触发 reload。这个值在源码中定义为singleFileWatchDebounce 500 * time.Millisecond目录由 fsnotify 监听见 wox.core/plugin/single_file.go 与 wox.core/plugin/single_file_watcher.go。文件系统事件的处理策略Create / Write→ 进入 500ms 防抖随后 reloadRemove / Rename→ 直接按路径卸载对应插件Chmod→ 仅记录日志以.开头的文件、.DS_Store、README.md、以及~/.tmp/.bak/.swp结尾的临时文件会被忽略不会触发 reload见 wox.core/plugin/single_file.go。reload 的行为契约reload 遵循以下约定理解它们对编写可热更新的插件至关重要每次加载或 reload 都会调用一次init()query/action 之间会保留插件对象状态常驻宿主进程的直接收益保存后内存状态重置。不提供状态迁移也不对旧实例做事务式回退reload 会先走现有 unload 路径因此 timer、watcher、socket 等可以通过 unload callback 清理metadata 永久无效时记录错误并保留旧实例解析失败、验证失败、ID 冲突都不会卸载正在运行的旧插件删除文件会卸载对应插件重命名会先卸载旧路径再等待新路径的 Create 事件。源码中reload 的完整调用链为handleSingleFilePluginEvent→debounceSingleFilePluginReload→reloadSingleFilePlugin检查文件存在 → 带 1 秒重试窗口读文件 → 解析并验证 metadata → 检查 ID 冲突 → 卸载旧实例 → 找到对应 runtime host → 必要时启动 host →loadHostPlugin见 wox.core/plugin/single_file_watcher.go。务必注册 unload callback只要插件创建了后台工作定时器、文件监听、WebSocket 等就应该通过 API 注册 unload callback否则 reload 时这些资源无法被正确释放。对应 API 为OnUnload底层实现把回调追加到pluginInstance.UnloadCallbackswox.core/plugin/api.go并在UnloadPlugin的deactivatePlugin阶段逐个执行wox.core/plugin/manager.go。共享目录与图标约束所有单文件插件共享同一个目录plugins/single-file/对应源码常量userSingleFilePluginsDirName single-filewox.core/plugin/single_file.go路径由GetUserSingleFilePluginsDirectory()统一提供wox.core/util/location.go。受共享目录限制需要注意不会加载共享的lang/目录只支持文件头里的内联I18n字段。测试用例TestParseSingleFilePluginMetadataDoesNotLoadSharedLang也验证了这一点wox.core/plugin/inline_metadata_test.gometadata 图标不能使用相对路径动态结果中也不要使用 relative image。支持以下图标形式emoji如emoji:️URLSVGbase64绝对路径源码中validateSingleFileMetadataIcon会解析图标并直接拒绝WoxImageTypeRelativePath类型wox.core/plugin/inline_metadata.go。需要自带资源文件图片、配置文件等时应升级为普通.wox插件。设置页和 WPM 中的打开插件目录会改为定位到具体的插件文件避免只打开混有多个插件的共享目录。商店发布分类规则商店不增加新字段。Wox 根据Runtime和 URL path 后缀分类query 不参与判断RuntimeURL 后缀类型PYTHON.py单文件 SDK 插件NODEJS.js单文件 SDK 插件PYTHON/NODEJS.wox普通 SDK 插件SCRIPT脚本文件脚本插件以下情况都会被拒绝未知后缀或无后缀后缀与 Runtime 组合不匹配例如PYTHON.js。更新与卸载约束更新时不允许同一个插件 ID 在.wox和单文件之间改变交付形态单文件商店条目必须显式声明MinWoxVersion且不低于该功能的首发版本文件头的Id、Runtime、Version必须和商店 manifest 一致源码中由ValidateSingleFileHeaderMatchesManifest强制校验见 wox.core/plugin/artifact.go并有对应测试 wox.core/plugin/artifact_test.go卸载只会把对应单文件移到回收站trash.MoveToTrash不会直接物理删除方便误操作恢复见 wox.core/plugin/store_single_file.go。安装流程的健壮性设计从源码看商店安装走的是专用的单文件安装流程installSingleFilePluginWithProgresswox.core/plugin/store_single_file.go有几个值得了解的细节先下载到临时文件.wox-single-file-download-*解析并校验 metadata 与后缀匹配后才落盘更新时先把旧文件重命名为.bak备份新文件就位并成功ReloadPlugin后才清理备份如果新版本加载失败会自动恢复备份并重新加载旧版本restoreBackup安装期间会调用IgnoreSingleFileWatch暂时屏蔽 watcher避免下载过程中的临时写入触发不必要的 reloadsingleFileManagedWriteWindow 2 * time.Second。结语单文件 SDK 插件是 Wox 插件生态中性价比很高的一种形态它保留了脚本插件单文件的便捷又通过常驻 SDK runtime host 获得完整 Public API、持久状态与进程复用。核心要点可归纳为正确声明内联 Metadata尤其Runtime与后缀匹配、理解保存即热重载的 500ms 防抖与状态重置语义、为后台任务注册 unload callback、遵守共享目录下的图标约束以及在商店发布时保持 manifest 与文件头一致。如果插件开始需要资源文件、npm/pip 依赖或多文件结构再平滑迁移到完整.woxSDK 插件即可。【免费下载链接】WoxA cross-platform launcher that simply works项目地址: https://gitcode.com/gh_mirrors/wo/Wox创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
📝

华诺云谱内容团队

资深建站顾问 · 行业研究员

10年+企业数字化服务经验,专注智能建站、SEO优化与品牌营销,持续输出建站技巧、行业洞察与营销干货,已帮助5000+企业实现数字化增长。

你可能需要的服务

订阅华诺云谱资讯周报

每周一封,精选建站技巧、SEO与营销干货,直达邮箱。已有 8,000+ 企业主订阅,助你少走弯路。