开始调用
如何调用 Host API
插件页面通常通过 RPC(页面与服务之间的方法调用)请求自己的服务,服务再调用 Host API。通知、面板标题和视频预览还提供专用页面方法。调用前,要在组件清单中声明所用接口和权限。
组件清单填写 componentHost.contractVersion:2,服务协议填写 protocolVersion:1。请求参数和返回类型可在 component-sdk/index.d.ts 中查阅。
用 project.media.page 读取媒体列表,用 project.output 保存结果,用 tasks 管理任务。
UI → 服务 RPC 属于组件自身实现,不等同于公开 Host 能力。
component-sdk 类型、运行时校验器与机器 schema 共同定义请求和结果。
每项能力都有对应权限,清单中需要同时声明。下表列出了完整的对应关系。
接口权限
每个接口需要哪些权限
清单中的 capabilities 表示插件会调用哪些接口,permissions 表示它申请的权限,两者都要填写。项目、当前文件夹范围(scope)和所选文件由照片流提供,插件不能自行替换这些信息。
全局设置页 application.settings 只允许已授权的设置、生命周期、对话框、通知和凭据接口;应用命令 application.command 还允许网络请求。它们都不能读写项目文件。对话框的具体操作也会单独检查。
project.media.pageproject.media.read分页列出项目中的媒体文件project.media.variantsproject.media.read获取缩略图、预览图或原图project.media.metadataproject.media.read读取尺寸、拍摄参数和视频信息project.files.pageproject.files.read分页读取其他文件、目录和配套文件project.files.searchproject.files.read搜索其他文件、目录和配套文件project.versions.pageproject.versions.read分页读取版本记录project.version.graphproject.versions.read读取版本和进度之间的关系project.media.ratingsproject.media.ratings.read批量读取媒体评分project.files.inputTokenproject.files.read + project.input.read取得任意格式项目文件的读取令牌project.files.watchproject.files.read检查文件修改、改名、删除和版本变化component.transferproject.input.read在插件页面与服务之间分块传输文件project.previewproject.preview.read读取当前预览视频和播放位置component.panelcomponent.panel读取或修改当前文件夹面板的标题project.input.tokensproject.input.read用读取令牌获取插件私有文件副本project.outputproject.output.write暂存、检查、保存或删除处理结果version.createproject.version.create用已保存的处理结果创建版本project.media.ratings.writeproject.media.ratings.write检查文件是否变化后逐项写入评分project.version.updateproject.version.write检查记录是否变化后更新版本project.version.deleteproject.version.delete删除版本,需要单独授权project.progressproject.progress读取、创建进度并记录来源project.progress.manageproject.progress.manage修改进度或取消登记和来源关系project.importproject.import用读取令牌批量导入文件project.files.mutateproject.files.write检查并执行文件操作,查询撤销结果project.media.processproject.media.process视频时间线帧与 Office 图片提取component.runtime.executecomponent.runtime.execute运行组件声明的命令,管理输入与后台任务component.storagecomponent.storage组件私有数据和 SQLite 位置component.settingscomponent.settings组件私有 JSON 设置component.mediacomponent.media访问组件私有存储中的媒体component.secretscomponent.secrets加密保存插件凭据,不返回明文network.fetchnetwork.fetch向允许的网站发送 HTTPS 请求taskstasks进度、检查点、取消与恢复dialogsdialogs确认、受限选择与已提交输出操作component.eventsevents发送已声明的组件事件notificationsnotifications显示简短的纯文本通知component.lifecyclecomponent.lifecycle.read查看插件权限、安装与运行状态project.files.inputToken 同时需要两项读取权限;project.files.watch 使用 includeVersions:true 时还需 project.versions.read;project.preview 跳转播放位置时还需 project.preview.control。
describe 使用 component.lifecycle.read;执行 preflight、install、repair 或 uninstall 还需要 component.lifecycle.manage。页面入口
如何添加插件入口、设置和通知
插件可以添加工具栏按钮、侧面板、右键动作、导入/导出入口和应用命令。每个入口只开放清单中列出的 RPC 方法;解码器等仅供宿主调用的方法,不能开放给普通页面。
工具菜单支持 workspace.videoTools(视频工具)、workspace.imageTools(图片工具)和 workspace.officeTools(Office 文档)。component.sidePanel 和 project.contextAction 可以选择这些位置,同时出现在文件选择右键菜单的对应分组中。菜单不会自动按后缀筛选输入,插件需要自己检查。
component.sidePanel 设置 placement:"workspace.folderPanel" 后,会加入文件页的面板菜单。用户可以固定、排序和拖动边界调整宽度。
application.settingsForm 可声明开关、选项、文本、数字和滑块,照片流负责显示并保存这些设置。
需要授权登录或诊断等复杂交互时,可给表单添加 customPage,或使用独立的 application.settingsPage。
component-sdk/ui.css 提供统一的颜色、间距,以及表单、按钮、卡片和对话框样式。
灵感库入口的 contentKind 为 inspiration,项目入口为 project。灵感库不提供项目版本树和进度操作。目录或选择变化时,通过 onContextChange 更新页面内容。
只提供设置的插件
如果插件只声明 application.settingsForm,且所有表单都没有 customPage,可以省略服务、工具页面和工具栏按钮。照片流直接显示并保存表单,不启动插件服务。名称、入口、图标和专属许可说明都应由插件清单提供。
在设置页显示许可说明
表单可声明 notices,每条包含 title、description、license、sourceUrl 和 licenseUrl,最多 64 条。两个链接必须使用 HTTPS,且不能带用户名或密码。只展示许可时可用 groups:[],但至少要有一条 notice。
绑定视频播放偏好
提供标准视频播放后端的插件,可在表单中设置 preferenceScope:"videoPlayback",直接读取和保存共享播放器的 HDR 偏好。只开放 hdrMode、toneMapping 和 targetPeakNits,不允许访问其他应用配置。
hdrMode 和 toneMapping 使用 select;targetPeakNits 使用 number 或 range,范围限制在 100–4000。选项还必须符合清单中播放后端声明的能力,例如 HDR 直通或对应的色调映射算法。普通表单仍保存到插件自己的设置中。
更新面板标题
声明 component.panel 接口和同名权限后,页面可调用 host.setPanelInfo({title, subtitle})。服务也可调用 component.panel 的 get/update。标题为 1–160 个字符,副标题最多 240 个字符,均为纯文本;只能修改当前文件夹面板。固定、关闭和排序按钮由照片流提供。
浮动工具面板由宿主测量正文高度,最高为 90vh;文件夹常驻面板则使用文件页分配的空间。不要在插件正文中重复绘制标题栏或关闭按钮。
发送通知
页面使用 host.notify,服务使用 notifications。
通知格式为 {tone,message,dedupeKey?}。tone 可选 info/success/warning/error,消息最多 360 个字符;可用 dedupeKey 避免重复提示。错误通知由用户关闭,其他通知约 3.5 秒后消失。内容必须是纯文本,不能包含 HTML、路径、URL 或执行命令,也不能设置 durationMs。
读取项目
如何读取项目文件和媒体信息
读取媒体列表、缩略图和原图
project.media.page 每页返回 1–200 项,继续翻页时使用返回的 cursor(分页游标),5 分钟内有效。project.media.variants 可获取最长边 320 像素的缩略图、1600 像素的预览图或原图。传入 variants:[] 只取媒体信息;请求原图时还会得到 10 分钟有效、只能使用一次的读取令牌。
查找其他文件和读取拍摄信息
project.files.page 与 project.files.search 用于其他文件、目录和配套文件。project.media.metadata 返回尺寸、相机、镜头、曝光,以及视频编码、时长和帧率等信息;没有的数据返回 null。结果使用项目相对路径,不返回电脑上的绝对路径。
读取版本关系和媒体评分
project.versions.page 和 project.version.graph 通过只读快照返回结果,不修改项目数据或索引。评分读取一次接受 1–100 个媒体引用;supported.labels 和 supported.selectionState 为 false,对应字段为 null。
文件资源
读取任意格式文件,并跟踪文件变化
取得文件副本
project.files.inputToken 接受 relativePath,可读取当前范围内任何格式的普通文件,包括没有后缀的文件。返回读取令牌、文件大小、SHA-256 摘要和 fileId。文件解析和编辑由插件负责。
随后调用 project.input.tokens 的 materialize,用令牌取得服务可读取的私有副本。令牌 10 分钟有效且只能使用一次,副本路径不能传给页面。可传入 expectedDigest 核对文件内容;文件发生变化时返回冲突,需重新读取。
检查文件是否被修改
project.files.watch 使用 subscribe → poll → unsubscribe。一次订阅 1–256 个已有文件;可见页面建议每 2–5 秒检查一次,每次保存返回的 cursor,同一订阅不要同时发起多个 poll。
事件包括 modified、renamed、deleted 和 versionChanged。按 sequence 去重;收到 rescanRequired:true 时重新核对文件。它反映文件状态,两次检查之间的多次变化可能合并,并不是完整操作记录。要读取变化后的内容,还需重新取得读取令牌。
每组件最多 16 个订阅,全宿主最多 256 个;5 分钟不调用就会过期。超过 30 秒没有轮询、游标不匹配或扫描达到上限时,都可能要求重新检查。页面释放或插件卸载时清理订阅。
分块传输大文件
component.transfer 用于插件页面与服务之间的二进制传输,不会上传到互联网。上传按 create → write → finish → close 执行;write 按 offset 顺序发送 base64,finish 用 expectedDigest 检查 SHA-256 并返回读取令牌。
下载时用 openInput 消费读取令牌,再用 read 按段读取,最后 close。上传每块原始数据最多 1 MiB,单文件及每组件活动上传合计最多 2 GiB;每组件最多 8 个会话,全宿主最多 64 个。10 分钟无操作会过期,宿主重启后需重新建立会话。
每块数据用独立 RPC 转发,避免超过单次 RPC 的 128 次嵌套接口调用限制。协议单帧仍限 2 MiB。服务已经能直接读取的文件,优先使用读取令牌或输出暂存区,减少不必要的数据传输。
预览扩展
让插件跟随视频播放,并支持更多文件预览
读取播放位置和跳转
声明 project.preview 和 project.preview.read 后,可调用 host.getPreview(),或用 await host.onPreviewChange(callback) 接收状态变化。返回的 video 包含 sessionId、relativePath、time、duration、paused 和 canSeek,时间单位为秒。没有可用视频时,video 为 null。
播放位置约每 250 毫秒更新一次,适合字幕高亮,不保证逐帧同步。页面隐藏或退出时,调用订阅返回的取消函数。接口仅对绑定来源文件页的项目或灵感库页面开放。
跳转还需 project.preview.control。调用 host.seekPreview(sessionId, time) 时使用刚读取的会话 ID,并先检查 canSeek。视频已切换、时间越界或不可跳转时会失败;accepted:true 表示请求被接受,实际位置以随后收到的状态为准。
为其他文件格式提供预览
在 componentHost.service.previewDecoders 中声明 id、label、extensions、method 和可选 priority。后缀支持自定义格式,也可用 * 匹配未知格式;插件仍需检查真实文件内容。解码方法必须列在 service.rpcMethods 中,只能由宿主调用。
只提供解码器的插件可使用空的 contributions:[]。至少声明 project.input.tokens、component.transfer 两项接口,以及 project.input.read 权限。每组件最多 16 个解码器,每个最多 64 条后缀规则,priority 范围为 -100~100。
宿主传入文件读取令牌、name、extension、从 0 开始的 pageIndex 和 maxEdge(64–4096)。服务取得输入副本后解码一页 PNG,通过分块传输接口获得输出令牌,返回 {inputToken, mimeType:"image/png", pageIndex, pageCount}。
PNG 宽高均不能超过 maxEdge,文件最多 32 MiB,总页数为 1–10,000。宿主检查并重新编码后显示图片,不接收 HTML、脚本、任意 URL 或本地路径。此接口用于静态图片预览,不提供文档编辑或交互式 3D。
安装并启用对应解码插件后,文件才会获得预览能力。解码失败时显示错误、重试和外部打开按钮;每文件页同时处理一个解码请求,全宿主最多 8 个,普通服务超时为 60 秒。
修改与保存
如何修改项目数据和保存处理结果
project.media.ratings.write逐项写入图片或 RAW 星级,每个文件单独返回结果;不支持视频评分、标签或选择状态写入。
project.version.update / project.version.delete传入 expectedUpdatedAt,确认记录自读取后没有变化再修改。删除版本需要单独权限。
project.progress.manage修改进度和来源关系时,检查节点属于当前项目范围,并防止出现循环关系。
project.import用一次性输入令牌导入文件,先暂存和检查,再保存到项目。处理中的令牌仍受原有到期时间限制。
project.files.mutate先用 preflight 检查计划,再用 commit 执行改名、移动、新建目录或移入回收站。每一步都有操作记录。
project.media.process仅支持 video.timelineFrames 与 office.extractImages。前者传入相对视频路径和时间点;后者传入稳定幂等键、文档相对路径和输出目录。
component.runtime.execute 调用组件运行时,具体用法见下方说明。保存新文件时,依次调用 project.output 的 stage、write、validate 和 commit;放弃未提交结果时调用 rollback。stage 最多 2,000 文件/2 GiB,24 小时后过期;项目目标必须是相对路径,绝对路径与 .. 无效。
保存新结果遇到同名文件时,默认返回冲突。commit 可传入 onConflict:"rename",由宿主另取文件名并保留已有文件。请使用返回的 relativePath 作为实际保存位置,requestedRelativePath 是原先请求的名称;已拥有文件的替换或摘要冲突仍需单独处理。
替换已提交文件时,提供 replace:true、该文件的 commit/artifact ID 和 expectedDigest。宿主核对文件摘要后再执行;发生冲突时保留用户改动并停止操作。
文件变更提交后应检查 undoAvailable;进入回收站不代表一定能自动撤销。遇到 outcomeUnknown 应停止并核实实际文件状态,不可重复执行删除或恢复。
数据与网络
如何保存插件数据、凭据和设置
component.storage获取组件专属的数据和 SQLite 存储位置。写入项目文件仍需使用项目输出接口。
component.settingsget 读取,replace 整体替换,merge 只合并第一层字段。JSON 对象最大 256 KiB,保存后返回新的修订号。
component.secrets用 Electron safeStorage 加密保存凭据。list 只返回凭据记录,不返回明文;无法加密或数据损坏时拒绝操作。
network.fetch只能请求清单允许的 HTTPS 网站。origin 是协议、主机名和端口;凭据通过已声明的请求头绑定注入,由宿主检查目标地址和重定向。
网络超时从读取凭据前开始计时,覆盖连接和响应全过程。卸载插件会中止正在执行的网络请求;关闭一个页面不会打断同插件其他页面的网络状态。
运行任务
如何运行组件程序和管理后台任务
component.runtime.execute 需要同名 capability 和 permission。execute 指定组件自身声明的 runtimeCapability 和参数;顶层 capabilities、runtimeCommandCapabilities 与平台入口共同定义可运行命令,不能传入任意可执行文件路径。
inputs.preview 接受当前范围内的 relativePaths 或受限 inputTokens,配合 input.extensions 筛选来源。
task.background:true 必须提供稳定的 operationKey 与 idempotencyKey。任务进入宿主任务中心;调用仍可能等待完成,UI 应独立监听进度。
status、cancel、pause、resume 使用相同 runtime capability 和操作键。取消、暂停需要运行时支持对应的 control 参数;resume 用于继续暂停任务。
eventName 必须在服务事件白名单中。projectArtifacts 登记预览或转码目录时另需 project.progress 能力及权限,并依赖已登记的项目来源节点。
运行时执行默认超时 20 分钟,可在 1 秒至 4 小时内指定 timeoutMs。清单授权、scope、输入令牌和组件归属仍由宿主复核;灵感库任务不应请求项目产物关系登记。
视频播放
如何添加视频播放后端
顶层 runtimeContributions 可声明 media.playbackBackend 协议版本 1,包括 backend ID、原生进程 transport、优先级、容器/编码探测和 transforms、HDR、统计、字幕、硬解、截图能力矩阵。
清单 priority 用于插件后端之间的排序,宿主还会参考 Chromium 的实际播放能力。
主程序提供统一播放器界面。插件可以另外声明原生设置表单,用于 HDR 偏好和许可说明,不需要创建自定义页面。
插件返回自己的 HWND;主程序验证所属 PID 后负责嵌入、DPI、定位与裁切。
普通 JSON 帧最大 256 KiB,禁止传输图像、像素或音视频帧;会话关闭后,其命令授权随之失效。
任务与错误
如何处理任务取消、失败和重试
tasks 提供 start/report/status/cancel/resume/complete/fail,用于开始任务、报告进度、查询状态、取消和结束。进度范围为 0–100;checkpoint(检查点)记录继续任务所需的信息,插件需要自己实现恢复步骤。收到取消请求后应停止工作并清理未提交结果。
页面 RPC 与服务 JSONL(每行一个 JSON 对象)消息最多 2 MiB。stdout 只输出协议消息,日志写 stderr。方法名、字段、权限、令牌和文件范围都会检查;不符合声明的请求会失败。
普通请求 60 秒超时。媒体处理和组件运行时执行可获得宿主批准的更长等待时间,其他 RPC 不会自动延长。
COMPONENT_HOST_INVALID_REQUEST
COMPONENT_HOST_PERMISSION_DENIED
COMPONENT_HOST_NOT_FOUND
COMPONENT_HOST_TOKEN_EXPIRED
COMPONENT_HOST_TOKEN_SCOPE
COMPONENT_HOST_LIMIT_EXCEEDED
COMPONENT_HOST_VARIANT_UNAVAILABLE
COMPONENT_HOST_CONFLICT
COMPONENT_HOST_CANCELLED
COMPONENT_HOST_TIMEOUT
COMPONENT_HOST_SERVICE_EXITED
COMPONENT_HOST_INTERNALretryable 或接口明确支持安全重试时重试。幂等键(idempotencyKey)用于识别同一次操作,重试时保持不变,避免重复导入或保存。数据管理
主程序和插件分别管理哪些数据
沙箱隔离只适用于组件 UI。service、生命周期脚本和 executable 是用户安装的受信本机代码,以当前用户的系统权限运行,可访问该用户的文件、网络和进程。Host API 权限约束正常接口调用,受监管进程不等于操作系统沙箱;应只安装可信来源的组件。
项目、媒体索引/变体、版本、文件安全、任务中心、组件生命周期、权限账本与受控发布。
私有存储、设置结构、算法、UI 状态、业务实体和自带的独立运行时。
插件应通过 Host API 修改项目数据,并自行管理插件数据库。卸载插件只移除代码,不自动删除组件数据。
从完整示例开始,了解清单、页面和服务如何配合工作。