• 简体中文
  • 插件 Quickstart

    先用 liyan plugin init 创建一个独立插件,构建打包,在 Desktop 导入、授权,再让 AI 调用 plugin.ping。整个流程不需要提交 PR、合入 LiyanLabs、注册官方目录或运行官方发布 CI;把匹配设备平台的包交给用户本地导入即可。

    需要业务工具时,可以继续复制飞书参考项目并增加只读工具 team.botInfo;需要 Capsule 界面时,参考本页的科学数据插件。项目有独立 go.mod,插件身份、工具和实现都在自己的项目中修改,无需重新编译宿主。

    飞书示例沿用现有的设备本地配置和消息适配。新平台的 Channel、新 Agent Runtime 仍需宿主扩展,见能力类型。

    准备环境

    需要包含本页能力的 LiyanLabs Desktop / Runner 和 Go 1.25 或更新版本。最小模板不需要飞书账号或其他业务凭据。复制飞书参考项目另需 Git、该项目指定的 Go 工具链,以及运行资源编辑脚本的 Python 3。宿主 CLI 和 Runner 使用 Rust;Go 是模板和参考插件的实现语言。

    本地工具 provider 没有实现语言白名单,Rust、Go、Python、Node.js 都可以实现同一契约。不过,只有 stdio 通信还不够:程序必须读取私有 bootstrap,完成约定的 stdio MCP 初始化、工具发现和调用,并与清单中的工具目录一致;配置注册入口另有注册协议。stdout 只输出协议帧。

    入口必须指向包内可在目标设备直接启动的程序,Runner 不通过 shell 启动,也不查找用户 PATH 中的解释器。当前 pack 收集声明的程序和资源,不会自动收集任意脚本、解释器或 pip/npm 依赖。Python / Node.js 作者需要交付包含所需运行时与依赖的可执行产物;普通的 python main.py 或 node index.js 项目尚无即装即用的打包支持。Go 示例不意味着其他语言已经有官方模板或完成了各平台运行验收。

    只有复制飞书或从源码构建 CLI 时才需要取得仓库;使用 Desktop 内置 CLI 创建最小插件可以跳过:

    git clone --recurse-submodules https://github.com/ScienceOL/Liyan.git
    cd Liyan

    已有 checkout 时,在仓库根目录运行 git submodule update --init --recursive。源码构建 CLI 会用到这些子模块。下文插件开发命令使用 Bash:macOS / Linux 使用终端,Windows 可使用 Git Bash;标为 PowerShell 的命令在 PowerShell 中运行。获取 CLI 与后续操作使用同一个终端,保留 plugin_cli 变量。

    获取并运行 CLI

    CLI 的命令名是 liyan,Windows 程序名是 liyan.exe;它同时是 Desktop 使用的 Rust Runner。安装 Desktop 不会自动把 CLI 加入终端 PATH。选择下面一种方式取得程序,然后检查帮助。

    使用 Desktop 内置程序

    使用包含 plugin 子命令的匹配版本 Desktop。macOS 默认安装位置:

    plugin_cli="/Applications/LiyanLabs.app/Contents/Resources/liyan"
    "$plugin_cli" version
    "$plugin_cli" plugin --help

    Beta 和 RC 分别将应用目录换成 LiyanLabs Beta.app、LiyanLabs RC.app;安装在其他目录时使用实际路径。Linux deb 的 Stable 默认路径为 /opt/LiyanLabs/resources/liyan;其他渠道使用各自安装目录下的 resources/liyan。AppImage 需先用其 --appimage-extract 选项解包,再使用解包目录 squashfs-root/resources/liyan。

    Windows 在 Desktop 快捷方式上选择“打开文件所在的位置”,取得安装目录,然后在 PowerShell 输入该目录:

    $desktopDirectory = Read-Host 'Desktop 安装目录'
    $plugin_cli = Join-Path $desktopDirectory 'resources/liyan.exe'
    & $plugin_cli version
    & $plugin_cli plugin --help

    Windows Git Bash 使用同一文件的 POSIX 路径,例如 plugin_cli="/c/实际安装目录/resources/liyan.exe",随后用 "$plugin_cli" 调用。

    从源码构建

    如果内置程序尚未包含这些命令,可以从当前源码构建。需要 Rust stable 和本机 C/C++ 构建工具链;Windows MSVC target 需要 Visual Studio C++ Build Tools,macOS 需要 Command Line Tools,Linux 需要 C 编译器和链接器。在前面取得的仓库根目录执行:

    cargo build --locked --manifest-path runner/Cargo.toml -p liyanlabs-cli --target-dir runner/target
    plugin_cli="$(pwd)/runner/target/debug/liyan"
    "$plugin_cli" version
    "$plugin_cli" plugin --help

    Windows PowerShell 使用:

    cargo build --locked --manifest-path runner/Cargo.toml -p liyanlabs-cli --target-dir runner/target
    $plugin_cli = (Resolve-Path 'runner/target/debug/liyan.exe').Path
    & $plugin_cli version
    & $plugin_cli plugin --help

    上述路径对应默认本机 target;如果显式设置了 Cargo build target,程序在 runner/target/<target>/debug/。Cargo 包名仍是 liyanlabs-cli,产出的可执行文件名是 liyan。

    确认可用与设置 PATH

    plugin --help 应列出 init、validate、pack、doctor。找不到文件时检查路径;提示不认识 plugin 时使用包含该能力的 Desktop / Runner,或从源码构建。版本号本身不能代替子命令检查。

    本页的智能体模板还要求 init 生成 skills/local-tools-setup/SKILL.md 和 skills/local-tools-usage/SKILL.md。如果你的 CLI 只有旧模板,更新匹配的 Desktop / Runner,或按上面的源码构建方式取得当前 CLI。不要把旧发行的能力当作本页所在源码提交的能力。

    本教程使用 "$plugin_cli" 的完整路径,无需安装全局命令。如需直接运行 liyan,可仅在当前 Bash 终端加入程序所在目录:

    export PATH="$(dirname "$plugin_cli"):$PATH"
    liyan plugin --help

    PowerShell 对应:

    $env:Path = "$(Split-Path -Parent $plugin_cli);$env:Path"
    liyan plugin --help

    init / validate / pack 不需要启动 Desktop、登录或连接设备;doctor 和聊天实际调用需要在线且已认证的匹配 Desktop / Runner。Desktop 管理自己的连接,插件开发无需额外启动 daemon 或手动执行 connect。

    创建第一个本地插件

    在上一步设置了 plugin_cli 的终端中创建项目。下面分别以 Windows x64 和 Apple Silicon Mac 为例;程序与 pack 目标必须匹配实际运行设备,其他目标见构建与打包。

    Windows PowerShell:

    $plugin_work_dir = Join-Path $env:TEMP ('liyan-local-plugin-' + [guid]::NewGuid().ToString('N'))
    New-Item -ItemType Directory -Path $plugin_work_dir | Out-Null
    & $plugin_cli plugin init (Join-Path $plugin_work_dir 'local-tools') --template local-provider
    Set-Location (Join-Path $plugin_work_dir 'local-tools')
    $env:GOWORK = 'off'
    New-Item -ItemType Directory -Path bin | Out-Null
    go build -trimpath -o bin/provider.exe .

    macOS Bash:

    plugin_work_dir="$(mktemp -d)"
    "$plugin_cli" plugin init "$plugin_work_dir/local-tools" --template local-provider
    cd "$plugin_work_dir/local-tools"
    mkdir -p bin
    GOWORK=off go build -trimpath -o bin/provider .

    模板生成 plugin.json、configuration.json、tools.json、图标、独立 Go 程序、项目 README,以及声明了 setup / usage 用途的两份 skills/*/SKILL.md。setup Skill 使安装后的“让 AI 帮我初始化”可用,usage Skill 说明如何调用工具。plugin.ping 已实现并返回 pong;配置没有凭据字段。init 不编译程序,未构建时验证会因入口文件缺失而失败。

    打包前编辑 plugin.json:将 name 改成自己的稳定标识(例如 com.example.my-tools),设置 author.name 和 extensions["com.liyanlabs"].displayName。保留宿主扩展命名空间 com.liyanlabs。模板的 provider 标签 example 不需要在宿主注册。首次版本可保留 1.0.0。

    智能体可直接编辑 JSON 文件。Windows PowerShell 也可以准确写入 UTF-8 无 BOM:

    $manifest = Get-Content -LiteralPath plugin.json -Raw | ConvertFrom-Json
    $manifest.name = 'com.example.my-tools'
    $manifest.author.name = 'My Team'
    $manifest.extensions.'com.liyanlabs'.displayName = '我的本地工具'
    [IO.File]::WriteAllText((Join-Path (Get-Location) 'plugin.json'), ($manifest | ConvertTo-Json -Depth 20), [Text.UTF8Encoding]::new($false))

    选择其他自己的标识时,后续聊天指令也使用同一个标识。不要改 localProviders[].provider 来代替插件身份;不同安装的相同 provider 标签会由宿主隔离。

    Windows PowerShell:

    & $plugin_cli plugin validate .
    & $plugin_cli plugin pack . --target windows-x64 --output (Join-Path $plugin_work_dir 'release-1.0.0')
    & $plugin_cli plugin validate (Join-Path $plugin_work_dir 'release-1.0.0/package.tar.gz')

    Apple Silicon Mac:

    "$plugin_cli" plugin validate .
    "$plugin_cli" plugin pack . --target darwin-arm64 --output "$plugin_work_dir/release-1.0.0"
    "$plugin_cli" plugin validate "$plugin_work_dir/release-1.0.0/package.tar.gz"

    输出目录必须尚不存在。validate 的结果应为 status: "valid",pack 应为 status: "packed"。交付文件是 release-1.0.0/package.tar.gz,其中已经包含程序、声明和资源。

    1. 在安装设备上启动并登录 Desktop,打开插件 → 导入本地插件,选择该压缩包;也可以直接选择已经构建好的项目目录。
    2. 检查名称、版本和设备,完成安装确认,审查本地执行及工具读取权限,并启用插件。
    3. 打开“待初始化”,选择 AI 帮助或手动配置,创建并保存真实设备配置;最小模板没有业务凭据,不需要飞书扫码或入站消息绑定。空配置仍需保存,不能跳过。
    4. 在使用该设备的聊天中发送:调用 com.example.my-tools 的 plugin.ping,报告工具实际返回的内容。 使用你填写的实际插件标识。
    5. 检查工具调用记录和返回的 pong。验证通过、列表中出现插件或 AI 自行回答 pong 都不能替代真实调用证据。

    有这次真实调用结果后,最小本地开发流程即完成。修改工具时同时更新 tools.json 和程序实现;修改已导入版本的内容时提高版本、重新构建打包并导入,更新后重新启用。详细更新和诊断步骤见本页后续章节。

    扩展自己的业务工具

    先确认模板的 plugin.ping 可以真实调用,再实现业务需求。普通工具作者只需要这个独立项目,不需要运行 LiyanLabs 服务栈、修改数据库或申请官方签名凭据。

    文件智能体需要修改什么保持的约束
    plugin.json身份、版本、名称、资源与入口声明包内相对路径;宿主扩展命名空间保持 com.liyanlabs
    tools.json完整工具名称、描述、输入 schema 和 readOnly与运行时 tools/list 逐项相同;不能只声明而不实现
    main.go解析 tools/call 的 params.name 和 params.arguments,执行业务并返回 MCP 内容stdout 只输出 NDJSON 协议,日志写 stderr
    configuration.json需要的原生配置字段凭据只由设备安全窗口收集,程序通过私有 bootstrap 读取
    bootstrap.go通常保持模板实现不编造安装、设备、版本和配置,不绕过 bootstrap
    skills/*/SKILL.md准确的初始化、使用和恢复说明同时在清单中声明 setup / usage;说明不授予权限

    例如增加只读 local.echo,可在完整工具列表中添加:

    {
      "name": "local.echo",
      "description": "Return the supplied text from the selected local device.",
      "inputSchema": {
        "type": "object",
        "properties": { "text": { "type": "string", "maxLength": 1024 } },
        "required": ["text"],
        "additionalProperties": false
      },
      "readOnly": true
    }

    这只是完整 tools.json 的一个工具元素,不是整个文件。保留顶层 schema: "liyanlabs.plugin-tools/1" 和 tools 数组;在程序中解析 arguments.text,验证参数,再返回 content: [{"type":"text","text":"用户传入的内容"}] 和 isError: false。模板用 go:embed 嵌入工具和配置资源,所以每次修改这些文件后都必须重新构建程序。

    模板已实现私有 bootstrap、MCP 初始化、工具发现和调用循环。增加业务处理时保留这条链路。改用 Rust、Python 或 Node.js 时,也必须完整实现该契约,并交付能被 Runner 直接启动的产物;语言不限不意味着任意 stdin/stdout 程序或一个裸脚本都能工作。详细协议见工具协议与运行产物。

    首次使用的完整验收

    阶段操作必须看到的证据
    创建plugin init,修改自己的身份项目中存在清单、程序源码、配置、工具和声明的 Skills
    构建构建目标平台程序,再 validate .valid、自己的 pluginKey、匹配的 target
    打包pack 后验证 package.tar.gzpacked;目录和 archive 验证的包摘要一致
    导入Desktop 选择压缩包或已构建的目录自己的名称与版本出现在目录;此时还没有完成安装
    安装打开该版本,点击“安装插件”所选设备的安装进入“已启用”;运行包确认完成
    配置“待初始化”选择 AI 或手动配置权限选择已保存、真实设备配置已保存
    检查“检查配置”,保持设备在线没有尚未完成的授权/配置要求;不要把未观测到健康误报成成功
    调用在使用该设备的聊天中要求调用真实工具调用记录、实际返回 pong 或业务结果

    手动路径是“待初始化 → 手动配置 → 批准所请求的访问 → 连接 → 打开安全凭据窗口 → 在原生窗口保存 → 检查配置”。空配置窗口没有凭据字段,也需要保存。用户可以拒绝权限;智能体应报告未授权状态,不得绕过。普通本地工具不需要选择接收入站消息的 Agent。

    AI 路径由包内 setup Skill 引导:读取当前状态、提问收集权限选择、准备原生配置、等待真实完成,再检查和调用。智能体不能在聊天中索取业务凭据,也不能把“连接请求已创建”当成“配置已完成”。如果执行开发的智能体没有 Desktop 操作能力,应交付压缩包的完整绝对路径,并明确提示用户完成上述原生导入/确认步骤;继续读取实际状态验证,不把打包完成报告为全流程完成。

    卡点与恢复

    现象检查与恢复
    终端找不到 liyan使用前面取得的绝对路径;检查 plugin --help,Desktop 安装不会自动设置 PATH
    init 报目录已存在使用一个新的项目目录;不会覆盖已有项目
    入口文件不存在或无法启动先构建;Windows 入口和文件名应带 .exe;核对设备 OS、架构与 pack target
    打包输出目录已存在使用新的输出目录;不要覆盖已发行的字节
    导入后只有目录项打开目录中的插件,继续安装;导入不等于安装
    AI 初始化入口不可用使用含 setup Skill 的模板;声明、文件与安装权限必须匹配;旧包添加 Skill 后提高版本再更新
    没有凭据字段却提示未配置创建并保存空设备 profile;不能伪造连接或配置版本
    聊天看不到工具核对确切安装已启用且确认、设备在线、配置和权限已完成;检查完整目录是否漂移
    返回 plugin_diagnostics_unavailabledoctor 使用当前已认证 Desktop 的同一渠道 home;等待设备连接成功后重查
    已安装包缓存丢失在原设备重导入确切版本,再按提示修复;不从服务器找回程序或换设备执行
    更新后旧工具仍显示新内容提高版本并重导入,更新已有安装、重新启用,再发起新调用;不要只覆盖源码

    失败时记录阶段、命令或操作、退出码/安全错误、插件版本与 target;不要输出凭据、bootstrap、设备签名 token。doctor 只观察已发生的会话;discoveryVerified: false 不能单独证明包坏了。业务结果始终以真实调用为准。

    复制飞书项目

    在源码仓库根目录执行,项目放在仓库外:

    plugin_work_dir="$(mktemp -d)"
    cp -R plugins/feishu "$plugin_work_dir/team-feishu"
    cd "$plugin_work_dir/team-feishu"

    参考目录包含:

    plugin.json                       作者清单
    assets/icon.png                   包内展示图标
    configuration.json                配置字段和原生注册入口
    internal/provider/catalog.json    飞书操作实现的声明
    internal/provider/                工具、认证和消息处理实现
    cmd/liyanlabs-plugin-feishu/       程序入口
    skills/feishu-setup/SKILL.md        初始化说明
    skills/feishu-usage/SKILL.md        使用说明
    tools.json                        由实现导出的公共工具目录
    go.mod / go.sum                   独立构建依赖

    名称与图标

    编辑 plugin.json 中的以下字段,并设置自己的作者和版本。它们分别决定插件身份、用户看到的名称和图标:

    字段本教程的值修改要求
    namecom.liyanlabs.team-feishu保持稳定;后续更新沿用同一标识
    version1.0.0发布后内容固定;修改内容时提高版本
    extensions["com.liyanlabs"].displayName团队飞书最长 128 个 Unicode 字符;不能只含空白或包含控制字符
    extensions["com.liyanlabs"].iconassets/icon.png指向项目内的图片;导入时随包读取

    com.liyanlabs 是宿主扩展命名空间,保持不变。保留 provider 标签 feishu 和现有 Channel 声明;不同安装可使用同一标签,配置和进程按完整安装身份隔离。同一个包内的 provider 标签必须唯一。

    参考项目已带飞书图标。替换 assets/icon.png 即可使用自己的图片;PNG、JPEG、WebP 均可,单张最多 256 KiB,宽高各为 1–1024 像素。声明使用小写扩展名 .png、.jpg、.jpeg 或 .webp 的包内相对路径,不能是链接、远程 URL 或绝对路径。图标属于公开展示元数据,程序和凭据仍只存设备。名称和图标修改后提高版本、重新打包,列表、详情与设置导航会使用新版本的展示信息。

    显示名称和图标都可省略:缺少名称时显示标识,缺少图标时使用通用图标。下面的脚本会写入本教程的名称和图标声明。

    增加一个工具

    这次复制已有的机器人信息查询,增加一个名字不同、描述清楚的只读工具。它会查询当前应用的机器人,不读取个人飞书账户,也不发送消息:

    python3 - <<'CODE'
    import copy, json
    from pathlib import Path
    manifest_path = Path("plugin.json")
    manifest = json.loads(manifest_path.read_text())
    manifest["name"] = "com.liyanlabs.team-feishu"
    manifest["version"] = "1.0.0"
    manifest["extensions"]["com.liyanlabs"]["displayName"] = "团队飞书"
    manifest["extensions"]["com.liyanlabs"]["icon"] = "assets/icon.png"
    manifest["author"]["name"] = "Your Team"
    manifest_path.write_text(json.dumps(manifest, ensure_ascii=False, indent=2) + "\n")
    catalog_path = Path("internal/provider/catalog.json")
    catalog = json.loads(catalog_path.read_text())
    assert not any(tool["name"] == "team.botInfo" for tool in catalog["tools"])
    tool = copy.deepcopy(next(tool for tool in catalog["tools"] if tool["name"] == "bot.v3.info"))
    tool["name"] = "team.botInfo"
    tool["description"] = "Get this team's configured Feishu application's bot identity. Read only."
    catalog["tools"].append(tool)
    catalog_path.write_text(json.dumps(catalog, ensure_ascii=False, indent=2) + "\n")
    CODE

    真实业务扩展还可以修改 Go 实现。readOnly 必须如实描述效果;写操作需要宿主审批。不要只改生成的 tools.json:运行时发现的名字、输入 schema 和只读分类必须与声明逐项一致,不一致时整份目录会被拒绝。

    构建与打包

    下面以 Apple Silicon Mac 为例:

    mkdir -p bin
    GOWORK=off go build -trimpath -o bin/liyanlabs-plugin-feishu ./cmd/liyanlabs-plugin-feishu
    ./bin/liyanlabs-plugin-feishu --describe-tools > tools.json
    "$plugin_cli" plugin validate .
    "$plugin_cli" plugin pack . --target darwin-arm64 --output "$plugin_work_dir/release-1.0.0"
    "$plugin_cli" plugin validate "$plugin_work_dir/release-1.0.0/package.tar.gz"

    验证输出包含 status: "valid"、pluginKey: "com.liyanlabs.team-feishu"、目标平台和包摘要;打包输出包含 status: "packed"、archive 大小与摘要。摘要随内容变化,不能照抄一个固定值。

    pack 创建 package-manifest.json 和 package.tar.gz。作者清单仍叫 plugin.json;生成的运行清单使用 liyanlabs.plugin-package/2,记录文件用途、大小、摘要和入口。输出目录必须尚不存在,并放在项目目录外;不要把上次 archive 再装进新包。验证不会执行插件代码。

    运行设备Go 构建目标pack 目标
    Apple Silicon MacGOOS=darwin GOARCH=arm64darwin-arm64
    Intel MacGOOS=darwin GOARCH=amd64darwin-x64
    Linux x64 / ARM64GOOS=linux GOARCH=amd64 / arm64linux-x64 / linux-arm64
    Windows x64 / ARM64GOOS=windows GOARCH=amd64 / arm64windows-x64 / windows-arm64

    构建目标必须匹配实际 Runner。Windows 将两个清单里的 provider 和 registration 入口都改成 bin/liyanlabs-plugin-feishu.exe,构建对应 .exe。使用 PowerShell 时把导出结果保存为 UTF-8 无 BOM;旧 PowerShell 的 > 可能生成 UTF-16。跨平台编译成功不等于已完成对应平台客户端验收。

    飞书示例保留可运行的业务实现和配置流程;不需要飞书业务时,使用前面的最小本地插件即可。

    安装和配置

    1. 在 Desktop 的插件页点击“导入本地插件”,选择项目目录或生成的 package.tar.gz。名称和版本从 plugin.json 自动读取,不需要手动输入标识。完成后在目录中查看该插件。
    2. 核对插件身份、版本和运行设备,完成安装和包启用确认。程序与 Skill 留在该 Runner;服务端接收声明、摘要、公开图标和安装元数据。
    3. 审核本地程序执行权限及业务读取权限。第三方包通过格式校验不会自动获得执行许可。
    4. 打开配置,创建命名 profile。扫码注册在 Desktop 原生窗口完成;已有飞书应用可输入区域、App ID、App Secret。不要把凭据发给 AI 或写入项目。
    5. 需要接收消息时,单独开启入站同意并选择 Agent。只查询机器人信息无需开启入站消息。

    包启用、配置完成和连接健康是三个状态。配置窗口由 configuration.json 驱动;注册程序只能输出约定的验证链接和配置结果,凭据保存在设备私有安全存储。安装页的 AI 帮助会使用包内 setup Skill,但不会替用户授予权限。

    调用与诊断

    在使用该设备的聊天中,让 AI 完成一个明确的只读任务:

    使用 com.liyanlabs.team-feishu 的 team.botInfo 查询当前配置应用的机器人身份。
    只读取信息,不发送消息或修改配置。告诉我实际工具返回的应用名称和状态。

    模型看到的工具名可能带宿主生成的安装前缀;Runner 给插件的原始工具名仍为 team.botInfo。成功证据是工具调用和实际返回的机器人信息,不能用静态校验或 setup 完成代替。

    doctor 是可选诊断,不是创建、安装或使用的前置条件。已取得安装操作/API 的 installation UUID 时在当前通道运行;不要把插件标识、release UUID 或设备 UUID 传给 --installation。没有 UUID 时先通过配置面板和真实聊天调用验收,不必为运行 doctor 阻塞使用:

    "$plugin_cli" plugin doctor --installation '<installation-uuid>'

    Dev Desktop 的 channel home 独立,开发时指定:

    "$plugin_cli" plugin doctor --installation '<installation-uuid>' --home "$HOME/.liyanlabs-dev"

    Doctor 通过当前通道私有诊断能力连接已认证的 Runner,输出设备、包确认与完整性,以及已经观察到的 provider 会话、配置和工具发现状态。它不读取凭据、不启动插件、不请求飞书 API。configurationObserved: false 或 discoveryVerified: false 可能表示尚未调用或会话正在执行,不能单凭它断言缺少配置;它也不是业务健康探测。没有当前 Desktop 连接时返回 plugin_diagnostics_unavailable,不会报告虚假的成功。

    目录漂移、配置失败或离线恢复参见开发与排障。

    更新和卸载

    修改内容后提高 version,重新构建程序、导出工具目录、验证并打包,再在原设备导入新版本。已发布的同身份同版本内容不能覆写。更新或修复后重新启用;配置绑定 release 与配置 schema,按新版本要求重新配置。不要通过改摘要、数据库状态或旧凭据绑定绕过确认。

    卸载通过插件页完成。旧进程和请求会被撤销,另一安装的同标签 provider 继续保持自己的生命周期。设备离线时能力不可用;不自动换机或转到服务端执行。该阶段没有公共第三方下载市场,分发方式是将匹配平台的本地包交给用户导入。

    Capsule 客户端界面

    需要界面时参考仓库的 plugins/science-data/:独立 provider 提供 PubChem、ChEBI、ChEMBL 查询,client/web 与 client/native 分别实现 React 和 React Native Capsule。它通过当前安装的模块图加载,导出 apply(ctx, config),在 ctx.effect 中拥有样式、资源订阅和清理。

    在 extensions["com.liyanlabs"].clientModules 中声明 id、platform、包内 entry、files 和 inject。Web 与原生入口分别构建为注册 factory 的 JavaScript;React 和 @liyanlabs/plugin-ui 由当前平台提供,必须声明依赖,不能打包第二份 React。先构建程序与客户端文件,再用同一个 liyan plugin validate / pack 验证并打包。具体构建命令见 plugins/science-data/README.md。

    科学数据也可以复制到仓库外,改成自己的插件并本地导入。它的 UI 和 provider 是一个包;不用加入官方 catalog,也不用运行 update-science-data-catalog.mjs。下面以 Windows x64 为例,在仓库根目录且已经设置 $plugin_cli 时运行:

    $capsule_work_dir = Join-Path $env:TEMP ('liyan-capsule-' + [guid]::NewGuid().ToString('N'))
    New-Item -ItemType Directory -Path $capsule_work_dir | Out-Null
    Copy-Item -LiteralPath 'plugins/science-data' -Destination (Join-Path $capsule_work_dir 'science-data') -Recurse
    $env:SCIENCE_DATA_ESBUILD_ROOT = (Resolve-Path 'frontend').Path
    Set-Location (Join-Path $capsule_work_dir 'science-data')
    $manifest = Get-Content -LiteralPath plugin.json -Raw | ConvertFrom-Json
    $manifest.name = 'com.example.local-science'
    $manifest.author.name = 'My Team'
    $manifest.extensions.'com.liyanlabs'.displayName = '我的科学数据'
    $manifest.extensions.'com.liyanlabs'.localProviders[0].entrypoint.path = 'bin/liyanlabs-plugin-science-data.exe'
    [IO.File]::WriteAllText((Join-Path (Get-Location) 'plugin.json'), ($manifest | ConvertTo-Json -Depth 20), [Text.UTF8Encoding]::new($false))
    $env:GOWORK = 'off'
    go build -trimpath -buildvcs=false -o bin/liyanlabs-plugin-science-data.exe ./cmd/liyanlabs-plugin-science-data
    node client/build.mjs
    & $plugin_cli plugin validate .
    & $plugin_cli plugin pack . --target windows-x64 --output (Join-Path $capsule_work_dir 'release-1.0.0')
    & $plugin_cli plugin validate (Join-Path $capsule_work_dir 'release-1.0.0/package.tar.gz')

    客户端构建需要 Node.js 和精确版本的 esbuild 0.27.4。上面的 frontend 必须已有依赖安装;第三方可以把 esbuild 单独装在自己的工具目录,无需安装宿主前端:npm install --prefix <工具目录> --save-exact --no-audit --no-fund esbuild@0.27.4,然后把 SCIENCE_DATA_ESBUILD_ROOT 设为该目录的绝对路径。Bash 对应 export SCIENCE_DATA_ESBUILD_ROOT="/absolute/tool-directory",程序入口和 pack target 按实际设备调整。类型导入会被构建移除;运行时依赖来自声明的平台注入,不能私自把宿主 React 再打包进去。

    完成导入、安装、空配置和权限确认后,从工作台菜单打开 Science data Capsule,选中该安装的连接,查询 PubChem 的 aspirin。验收应看到真实分子记录及 Runner 返回的结构图;界面能打开不证明查询或图像链路成功。原生模块同包提供,但桌面验收不代表已完成手机/平板客户端验收。

    UI 代码直接运行在客户端的 JavaScript 环境中,安装前需要信任作者。ctx.resources 提供按地址共享、末位释放时取消的资源;ctx.connections.list 只返回公开连接状态;ctx.tools.call 仅调用当前获准的只读工具,并通过选定在线 Runner 执行。界面不获得操作凭据或服务端执行权限。更新、禁用、卸载、权限撤销或设备离线会撤回旧模块。

    交给 AI 开发

    下面的提示可和本页一起交给开发智能体。先完成最小本地闭环,再添加用户业务;不需要先提交仓库 PR。

    目标:创建一个独立 LiyanLabs 本地插件,并在我选定的 Desktop 实际调用成功。
    按本页先检查 liyan CLI 和 Go,使用 plugin init 生成独立项目。
    使用自己的稳定身份、作者和名称;保留私有 bootstrap、协议循环以及 setup/usage Skills。
    先构建 plugin.ping,validate 项目,按实际设备平台 pack,再 validate archive。
    每一步读取退出码和真实输出;失败就定位和修复,不靠猜测继续下一步。
    通过 Desktop 导入,打开该插件安装并确认,在所选设备保存权限和真实配置。
    空配置也需要保存;只在原生窗口输入凭据,不改数据库,不关闭权限或完整性检查。
    用该设备的聊天实际调用 plugin.ping 并验证工具返回 pong,然后实现我的业务工具。
    业务工具的输入 schema、只读/写操作性质和运行时发现必须与声明完全一致。
    修改已导入内容时提高版本、重建、重打包、更新安装并重新启用,再实际调用验收。
    如果你的工具无法操作 Desktop,先交付包的完整绝对路径和所需的原生确认步骤。
    交付:源码路径、包路径、插件身份/版本/target、构建和校验输出、安装/配置状态、真实调用证据。
    未取得真实调用证据前,不报告已完整完成;不要增加社区、PR、官方 CI 或市场上架前置条件。

    飞书业务扩展示例:

    阅读 LiyanLabs 插件 Quickstart 和总览的能力类型。
    复制 plugins/feishu 到仓库外的独立项目,使用 com.liyanlabs.team-feishu 身份。
    在业务目录中增加只读 team.botInfo,保持现有 Feishu Channel 契约。
    在项目内构建程序,--describe-tools 导出 tools.json,再 validate、pack、验证 archive。
    不要修改宿主源码,不把凭据写入包、聊天、日志或普通 Web 表单。
    在用户选定的 Desktop 导入并完成原生配置和权限审查,实际调用新增工具。
    分别报告静态验证、安装确认和真实调用证据;未完成的步骤明确说明。