插件开发与排障
使用本手册启动本地插件栈、配置 device-local provider、追踪生命周期失败,并在不削弱 local-first 边界的前提下扩展目录能力。
本地环境
从同一个 checkout 启动常规服务栈与 Desktop/Runner:
本地 origin 是 https://scilaxy.local。不要同时从两个 worktree 运行完整 Compose 栈;stack、数据库、Redis、端口和 Desktop 连接都是共享资源。
just dev 会在服务启动前准备 Dev 插件 authority。desktop/scripts/provision-dev-plugin-runner.mjs 生成或复用以下忽略提交的本地材料:
- Dev 服务端 Ed25519 signing key;
- plugin-secret 加密 keyring;
- Dev channel home 下的公开 trust resource。
just desktop-dev 生成并暂存 runtime manifest、填充本地 runtime cache、构建 Runner、启动 Electron。API、Web、Worker 在 just dev 下热更新,普通源码修改不需要重建整套栈。
排查插件前确认:
- Desktop 显示 channel
dev、backend originhttps://scilaxy.local。 - Trust resource 指向精确 WSS origin 和
/scilaxy/ws/v1/runner/device路径。 - Desktop enrollment 是
active,lease expiry 持续推进,并存在 catalog digest。 - Installation 与指定 device 属于同一个认证用户。
配置本地 Profile
飞书或 GitHub 必须先完成 connection,再启用:
- 安装插件并选择在线 Desktop。
- 输入 profile label。Trim 后必须有 1–128 个 Unicode code point,且只包含字母、数字、空格、
.、_、-。 - 点击“前往桌面端配置”,创建
authorize_local_profiledevice action。 - 完成隔离 Electron 窗口。飞书需要
cn或global、App ID、App Secret。 - 等待 connection 进入
ready,本地 provider probe 健康。 - 审核并保存插件请求权限。
- 启用 installation。
Connection 与 permission 的先后可以交换,但二者必须存在。Profile label 为空时,前往 Desktop 的按钮会按设计禁用。
插件包契约
每个可移植 package 都包含根目录 plugin.json,遵循 Agent Plugins 1.0.0。Skill 从 skills/<name>/SKILL.md 发现;可选根目录 mcp.json 声明 MCP server。SciLaxy 专属本地执行能力声明在 extensions["ai.scilaxy"]。
最小 local-provider manifest 结构如下:
示例 tool-catalog digest 必须替换为真实小写 SHA-256。Extension 是闭合 schema:localProviders 可以定义 package-relative stdio provider;inboundTransports 可以定义 provider WebSocket 或需 ACK 的 webhook relay;channels 当前只接受受支持的飞书/GitHub contract;agentRuntimes 仅允许 builtin source 和受支持 adapter。
校验是确定、离线且不执行代码的,也不获取远程 schema。Package 只能包含普通文件和规范安全相对路径,禁止 link/device/socket 和带 credential 文件;最多 2,000 个文件、64 MiB 解压数据、32 层路径,压缩比不超过 100:1。非 bundled local provider 还必须在指定设备取得显式 host-authority consent。
API 表面
认证插件 REST 根路径为 /scilaxy/api/v1/plugins:
Runner 通道为 WSS /scilaxy/ws/v1/runner/device。GitHub 公网 ingress 为 POST /scilaxy/api/v1/plugin-webhooks/github/:endpoint_token。
规范 REST 路径没有尾斜杠。请求和响应的事实源位于 service/pkg/web/views/plugins/、plugindevices/、runnerws/。
Readiness 失败
启用会提交异步生命周期命令。API 可以接受请求,而 Worker 随后仍会拒绝。必须同时读取最新 plugin_installation_operation 和 installation health blocker。
Operation 级 requirements_unmet 只表示存在一个或多个 blocker,本身不等于 lease、signing 或 App Secret 失败。
一个常见的新飞书安装失败会同时具备:
- installation 是
disabled; - 最新 Enable operation 以
requirements_unmet失败; - 没有
ready的plugin_connection; - 没有当前
plugin_permission; - device enrollment 与 lease 健康。
此时重复登记设备、轮换服务端 key 或继续点击“启用”都不会恢复。应先完成本地 profile 和权限。
设备连接失败
设备 transport 与生命周期 readiness 必须分层排查:
不要把它们全部归为“租约问题”,每层的恢复动作都不同。
数据库诊断
只使用只读查询,不打印 secret、ciphertext、nonce、原始 provider payload、ticket 或本地路径。
列出当前 23 张表:
追踪 installation 和最新 operation:
检查非秘密 connection 与 permission authority:
检查 liveness 而不暴露 key material:
Enable 失败建议顺序:
- 最新 operation error code;
- health blockers;
- ready connection;
- 当前 permission coverage;
- 绑定 device lease/generation;
- 最后才查本地 runtime/package/provider health。
新增插件
- 在唯一 catalog/manifest 事实源声明 plugin identity、immutable release、capability 和平台 runtime,不在可执行代码重复部署或展示事实。
- 复用闭合 capability schema。新增协议概念必须同步更新 validation、数据库 contract、API projection、Runner 和测试。
- 选择唯一 credential owner:device-local、server OAuth 或无 credential,不得混用。
- 使用 package-relative provider entrypoint 和闭合 argv、working directory、transport、verifier schema,禁止拼接 shell。
- 声明最小权限。外部写操作必须接入 effect intent、审批、receipt、reconcile。
- 入站事件使用本地长连接或受控 webhook relay,不增加云端执行 fallback。
- 测试 install、setup、permission、offline device、generation fence、revoked release、protocol drift、重试与歧义。
- 为 Web、Desktop、移动端提供等价状态和恢复信息。
- 同时更新中英文 Rspress 页面和 provider 专属文档。
- 使用真实 Desktop/Runner 完成从安装到 provider 调用的端到端验证。