插件开发与排障
本页供接入业务工具和排查运行问题时查阅。创建第一个包先读 Quickstart;本文中的 provider 指提供业务工具的本地进程,profile 指设备上保存的命名配置。
本地环境
从同一个 checkout 启动常规服务栈与 Desktop/Runner:
首次使用先从 docker/.env.example 创建私有的 docker/.env.dev,按仓库开发环境说明配置模型网关等服务。示例配置中的模型凭据为空,直接启动 API 会失败。Dev 插件签名准备也需要这个文件。
本地 origin 是 https://liyanlabs.local。不要同时从两个 worktree 运行完整 Compose 栈;stack、数据库、Redis、端口和 Desktop 连接都是共享资源。
just dev 会在服务启动前准备 Dev 插件签名与信任配置。desktop/scripts/provision-dev-plugin-runner.mjs 生成或复用以下忽略提交的本地材料:
- Dev 服务端 Ed25519 signing key;
- 服务端加密 keyring(不用于保存 device-local 操作凭据);
- Dev channel home 下的公开 trust resource。
just desktop-dev 生成并暂存 runtime manifest、填充本地 runtime cache、构建 Runner、启动 Electron。API、Web、Worker 在 just dev 下热更新,普通源码修改不需要重建整套栈。
排查插件前确认:
- Desktop 显示 channel
dev、backend originhttps://liyanlabs.local。 - Trust resource 指向精确 WSS origin 和
/liyanlabs/ws/v1/runner/device路径。 - Desktop enrollment 是
active,lease expiry 持续推进,并存在 catalog digest。 - Installation 与指定 device 属于同一个认证用户。
配置本地连接
本地 provider 的配置与包启用独立。首次安装保存启用意图;更新或修复后需重新启用。
- 选择在线 Desktop 并安装插件,等待包确认完成。
- 打开配置入口。带 setup Skill 的插件可选 AI 帮助,也可手动配置或稍后配置;新 CLI 模板已包含 setup / usage Skills。
- 创建命名本地 profile。Label trim 后为 1–128 个 Unicode code point,允许字母、数字、空格、
.、_、-。 - 在绑定 Desktop 的原生窗口完成配置。飞书优先扫码注册;“使用已有应用”提供区域、App ID 与 App Secret 输入。GitHub 使用其设备本地 token 配置。
- 审核业务权限。空配置也须保存;普通本地工具不需要外部账号或入站 Agent。飞书入站消息默认关闭,需要时单独同意并绑定 Agent。
- 通过 setup reconcile 刷新配置状态,再查看设备和 provider 是否健康。
操作凭据只进入设备安全存储,不粘贴到聊天、manifest、普通 Web / Mobile 表单或日志。保存配置只证明本地存储成功;连接健康仍需认证探测。AI plugin_setup 的 status 是读取,reconcile 是维护动作,继续遵守当前会话权限模式。
插件包契约
作者清单是根目录 plugin.json,使用 Agent Plugins 1.0.0;宿主扩展使用 extensions["com.liyanlabs"] 和 extension 2.0.0。工具实现、资源和入口随插件一起发布。可复制的完整示例见Quickstart。
入口和资源都使用包内安全相对路径。id 是 capability 标识,provider 是配置和协议标签;一个包内各标签唯一,跨安装允许重复。它们不代替完整安装身份。普通 provider 不需要在宿主登记名字。
tools.json 使用 liyanlabs.plugin-tools/1:每项包含 name、description、inputSchema 和显式 readOnly。输入 schema 离线编译,禁止外部资源获取。configuration.json 使用 liyanlabs.plugin-configuration/1:title、fields 和可选 registration;字段类型为 text / password / select,并声明长度、是否必填、选项和默认值。没有凭据需求时可声明空字段列表。
注册入口同样是包内程序。它输出逐行 verification(URL、expiresIn)、configured(values)或闭合 error 帧;URL 只能来自声明的 HTTPS origins。Desktop 仅向普通界面展示安全验证链接,主进程校验并保存结果。取消、退出和设备撤销会清理整个进程树。
Skill 位于 skills/<key>/SKILL.md 并显式声明 setup / usage;MCP HTTP 声明、其他 Channel 和 Runtime 的限制见能力类型。验证不执行代码,不获取远程 schema;拒绝未知字段、重复 JSON key、链接、特殊文件和不规范路径。最多 2,000 个文件;非程序资源总量不超过 64 MiB,运行包总量不超过 512 MiB。普通第三方程序需用户明确同意本地执行权限。
工具输入 Schema 支持 JSON Schema draft-07(http://json-schema.org/draft-07/schema#)和 2020-12(https://json-schema.org/draft/2020-12/schema)。省略 $schema 时使用 2020-12。命令行和导入均离线校验,引用必须留在当前文档内。
工具协议与运行产物
区分设备桥与插件进程:plugin-provider/1 和 plugin_provider.tools.list / call 是宿主与 Runner 的受认证请求;作者的 stdio 程序接收 MCP JSON-RPC 2.0 方法 initialize、notifications/initialized、tools/list、tools/call,不解析设备桥 envelope。
Runner 先验证可执行文件与完整安装绑定,再通过私有继承 FD / Windows handle 提供一次性 plugin-provider-bootstrap/2。定位变量是 LIYANLABS_PROVIDER_BOOTSTRAP_FD;其中含精确 binding、配置 schema 摘要、配置版本、私有配置值和本地数据目录。读取后关闭并清除定位变量。凭据不进入 argv、普通环境变量、工具参数或 stdout。飞书代码演示该读取边界。
程序 stdout 只输出有界逐行 MCP JSON。请求示例:
对应结果:
发现结果的 annotations.readOnlyHint 必须为显式布尔值并与资源分类一致。Runner 匹配整份工具目录的数量、唯一名字、schema 和分类,再允许调用;禁止缺项、意外工具或重复名。数据错误和业务失败使用受支持的 MCP 结果,不能把凭据和本地路径放进错误。当前支持 MCP text / image 内容;structuredContent 须为对象,由 Runner 投影为 json 内容。image 使用规范 Base64,单张解码后最多 256 KiB,MIME 为 PNG / JPEG / WebP / GIF / SVG。不接受任意 resource、audio 或文件块;以 provider/mcp.rs、provider/image.rs 为准。
模型工具描述包含完整 plugin、installation、capability 和原始工具名称,帮助智能体区分同名工具;不要猜测前缀或搜索插件私有目录。Runner 收到的仍是原始名称。
Runner 持续复用同一完整绑定的进程,并序列化其交换。配置版本或 binding 变化、超时、取消、禁用、更新、卸载和设备撤销会退休会话并清理辅助进程。插件不能自行跳过审批或向另一个安装借用配置。
目录验证会生成同一运行索引;archive 验证核对全部字节与声明。导入在确切 Runner 上准备,服务端只保存 liyanlabs.plugin-native-metadata/1 声明、索引摘要及声明的公开图标,不接收程序或 Skill 字节。准备回执有期限且只能被一个安装认领;重试可重放同一操作。缓存缺失需在原设备重新导入。
第一方可下载 runtime 仍由 Desktop 构建固定,Runner 按需验证并缓存。OpenSDL 使用相同 /2 文件索引,执行仍是已有 opensdl/1 gRPC 适配;没有人为改成 stdio provider。公共第三方下载发布不在本阶段。
API 参考
需要登录的插件 REST 根路径为 /liyanlabs/api/v1/plugins:
Runner 通道为 WSS /liyanlabs/ws/v1/runner/device。GitHub 公网 ingress 为 POST /liyanlabs/api/v1/plugin-webhooks/github/:endpoint_token。
规范 REST 路径没有尾斜杠。请求和响应的事实源位于 service/pkg/web/views/plugins/、plugindevices/、runnerws/。
安装和配置失败
诊断时分别读取安装 operation、setup 与 health。包安装或确认失败、尚未配置和 provider 连接失败属于不同层,不应统一解释为“先配置才能启用”。
新飞书包已启用而仍需配置属于正常状态。此时完成原生配置与权限审查,再 reconciliation;不要重复登记设备或轮换服务端 key。配置后仍无工具时,核对当前 release 的工具资源、完整发现匹配、权限和连接绑定。使用 Quickstart 的 doctor 查看本地包确认与已观察到的会话状态;它不是业务健康探测。
设备连接失败
设备 transport 与生命周期 readiness 必须分层排查:
不要把它们全部归为“租约问题”,每层的恢复动作都不同。
数据库诊断
只使用只读查询,不打印 secret、ciphertext、nonce、原始 provider payload、ticket 或本地路径。
列出数据库实际插件表:
追踪 installation 和最新 operation:
检查连接元数据和权限版本:
检查设备在线租约:
调用不可用建议顺序:
- 最新 operation error code;
- health blockers;
- 当前 setup requirements;
- connection 与 permission coverage;
- 绑定 device lease/generation;
- 最后才查本地 runtime/package/provider health。
新增插件
普通本地工具在独立项目中实现,无需为新 provider 修改宿主。按 Quickstart 复制飞书,或使用 plugin init --template local-provider 创建空白项目。
- 声明稳定身份、版本、工具与配置资源,构建匹配设备的平台程序。
- 导出真实工具目录,静态验证、打包,并在选定 Desktop 导入。
- 使用原生配置和最小权限,验证一次真实业务调用。
- 验证目录漂移、取消、更新、禁用、离线与另一安装的隔离;写操作验证审批和不明结果对账。
- 提高版本重新打包分发,用户在原设备导入更新并重新启用。独立插件不需要宿主 PR 或官方 CI。
新平台 Channel、新 Agent Runtime 及远程发布需同时设计声明、授权、运行和清理消费者。客户端模块使用 clientModules 声明,参考 plugins/science-data/client/ 的平台入口与 apply(ctx, config)。它们不能只通过增加 manifest 字段实现。支持范围见总览的能力类型;保持设备本地执行与无离线 fallback。
第一方发行构建
本节描述项目维护的官方发行路径;独立插件的本地创建、打包和导入不需要加入这个 registry,也不需要运行该工作流。
第一方可下载插件通过 desktop/scripts/plugin-release-registry.mjs 的 registry 接入,声明工具、程序与 npm 包根。plugins.yaml 统一负责 plan/probe/build/publish;应用工作流只解析精确的已有发行。编译输出与安装目录归 job 私有,共享缓存只保留不可变、已验证的字节。Science data 的 provider 与 Web/Native 模块打包为同一个插件。官方可下载 runtime archive 与第三方导入包各有自己的清单契约;统一 CI 不表示任意官方下载文件都可直接拿来本地导入。第三方应通过 liyan plugin pack 生成导入包。