安全与参考插件发布 V1

安全与参考

插件发布 V1:作者与智能体指南

本文给插件作者、开发智能体和内置 QA 智能体使用。目标是把一个插件准备成可审核的官方市场内容,让用户在支持该链路的客户端中刷新、添加或更新,无需为每个新插件重装客户端。

V1 指官方内容分发协议。插件自己的版本、客户端版本、后端 Host API 和前端 UI SDK 分别管理。本文描述代码支持的流程,不代表某个历史安装包已经具备全部能力;以目标安装包的交付记录和实际验收为准。

接到任务先确认输入

输入要求
任务范围区分解释文档、开发插件、准备内容 PR、正式发布。已有明确授权就继续;“准备插件”不自动包含生产发布。
插件身份稳定 ID、新 SemVer、开发源码位置、要交付的运行文件。示例 ID example-echo 不是待上架商品。
用户任务用户装好后在哪里、通过哪些操作完成什么工作;给出可复现验收步骤。
兼容目标明确客户端安装包、平台、后端 Host API 范围;有前端时还要确认 UI SDK。
外部条件实际许可证、第三方服务、配置项、网络域名、文件/进程操作与凭据使用。
发布权限普通作者提交包和元数据,由有权限的维护者审核并签名发布。没有仓库权限时交付运行包和元数据,不索要生产私钥。

缺少输入时先列出缺口,可以继续完成不依赖它的开发和校验。不要猜兼容范围、许可证或生产发布授权。QA 智能体默认负责检索、解释与交接;实际修改和发布以当前任务授权及自身能力为准。

文件放在哪里

正式内容源由 CogineWork 仓库维护,无需另建管理应用:

text
official-assets/v1/
├── publication.json
└── packages/plugin/<id>/<version>/<id>/
    ├── plugin.json
    ├── plugin.py
    ├── LICENSE
    └── dist/index.js       # 可选的已构建前端入口
official-assets/presentation/v2/source.json

publication.json 管身份、安装兼容、权限和状态;当前展示源是 official-assets/presentation/v2/source.json,管分类、精选、图标和详情。正式发布从这份 v2 源生成兼容旧客户端的 presentation.json 和新版 presentation-v2.json,两个输出仍发布在 metadata/official-assets/v1/ 路径下。presentation/v1/source.json 保留给旧工具兼容,不是当前正式发布的内容输入;只改它不会更新正式展示。

官网与 QA 共用本页,客户端读取发布后的签名目录和运行包;仅把代码提交到开发仓库不会自动上架。

下文所有仓库相对路径以 CogineWork 源码根目录为起点。只有安装包、没有源码的智能体可以准备交付材料;不要假设安装目录里有 CI 配置、测试或发布器。

第一步:准备已构建的运行包

plugin.json 至少一个后端或前端入口,身份和版本必须与目录一致。下面仅演示格式,兼容区间必须换成经过验收的目标范围,不能直接把示例当作生产条目:

json
{
  "schema_version": "official-plugin-manifest-v1",
  "id": "example-echo",
  "name": "Example Echo",
  "version": "1.0.0",
  "description": "Echo text for a plugin authoring example.",
  "author": "Cogine",
  "type": "tool",
  "entry": { "backend": "plugin.py" },
  "dependencies": [],
  "coginework_version": { "min": "2.4.0-beta.5", "max": "4.0.0" },
  "plugin_host_api": { "min": "1.1.0", "max": "2.0.0" },
  "meta": {}
}

区间语义为 >=min,<max。清单使用协议 SemVer,例如 2.4.0-beta.5;不要直接复制 Python 包版本 2.4.0b5。示例下界不是对该历史桌面包的功能保证。

最小后端入口 plugin.py:

python
from coginework.plugins import PluginApi


async def example_echo(text: str) -> str:
    return text


class EchoPlugin:
    def register(self, api: PluginApi) -> None:
        api.register_tool(
            tool_name="example_echo",
            tool_func=example_echo,
            description="Echo the supplied text.",
        )


plugin = EchoPlugin()

模块必须导出 plugin 并实现 register(api)。未声明工具治理的工具在受管模式下可能要求批准。文件、网络和进程工具应按宿主合同使用 ToolGovernance/ToolEffect;市场里的权限声明不等于运行时授权。

包准备规则:

  • 后端入口是包根目录的 .py,前端入口是包内 .js/.mjs,声明的文件必须存在。
  • 有前端时使用仓库 console/plugin-sdk/ 和 console/examples/frontend-plugin-template/ 的 README,先构建单文件 ESM 再放进运行包。不要假定 SDK 已发布到公共 npm。
  • 官方 V1 运行包不允许 requirements.txt、package.json 或 pip/npm 安装命令;运行依赖按下节准备。
  • 放入实际 LICENSE;不放凭据、.git、虚拟环境、缓存、node_modules、符号链接或临时制品。
  • 官方包由发布器生成确定性 ZIP,当前最多 50 MiB、1024 文件;单文件最多 32 MiB,解包总量最多 200 MiB。

运行依赖怎么准备

依赖类型当前规则
plugin.json.dependencies声明宿主提供的依赖;当前官方发布白名单为空,填写 []。不能把任意 pip/npm 包名写进去期待安装时补齐。
publication.json 条目的 dependencies声明其他市场资产的精确 {kind,id,version},由客户端生成安装计划;不是 Python/Node 包依赖。
构建依赖与随包代码作者可以在开发项目中使用构建依赖,将适合分发的运行代码打包或 vendor 到产物中,并保留相应许可证;只交付通过包校验的运行文件。
MCP 运行产物支持该链路的客户端可按 mcp_install 声明准备独立 MCP 产物,规则见下文;它不为普通插件提供任意依赖安装。

后端可依赖的稳定扩展接口以对应的 Host API 合同为准,包括 PluginApi 和工具治理类型;dependencies: [] 不表示禁止导入这些接口或合规的包内模块。

后端 Python 插件加载在 CogineWork 后端进程中。技能脚本使用的独立 Python/Node 及其预装库,不代表后端插件能直接导入同一批库,也不代表任意第三方依赖已具备。作者应对目标客户端、系统和架构验证实际依赖,写清外部软件与准备步骤,不把本机开发环境当作接收者环境。

桌面构建会为独立 Python 准备部分文档库,例如 python-docx、openpyxl、python-pptx、pypdf;实际版本和可用性应在目标安装包中检查,Node 的模块也应单独检查。LibreOffice、Poppler、pandoc、中文字体等仍是需要作者明确列出的外部条件,并非都已随客户端提供。

官方 MCP 连接器可以在 plugin.json 中声明 mcp_install(schema_version: mcp-install-v1):固定 runtime.version、制品完整性摘要 integrity、启动参数及所需解释器,并按实际支持情况声明平台制品。运行来源支持 npm、pypi、url、sidecar;宿主准备过程(provision)负责下载或复制、校验、展开该产物,不会递归运行 npm/pip 安装它的依赖。作者仍需准备能独立运行的产物或提前解决依赖;指向 npm/PyPI 包并不等于它的运行依赖已齐备。

例如仓库的 pexels-mcp 包先把 MCP 及其运行依赖构建为 runtime/pexels-mcp-server.mjs,再用 sidecar 和固定 SHA-256 声明交给宿主准备。可参考 official-assets/v1/packages/plugin/pexels-mcp/1.0.1/pexels-mcp/plugin.json;示例不代表其他 MCP 或所有平台已经验收。API Key、OAuth 等凭据由接收者配置或授权,通过声明的凭据引用使用,不放入发布包。

第二步:准备完整安装条目

以下是新增 publication.json.assets 条目的模板。两个时间占位符和许可证摘要必须替换为真实值;它不是可以原样发布的 JSON。statement、下载 URL 和制品路径由维护者的发布器生成,不手写。

json
{
  "schema_version": "official-asset-v1",
  "kind": "plugin",
  "id": "example-echo",
  "version": "1.0.0",
  "package_profile": "plugin-bundle-v1",
  "name": { "en-US": "Example Echo", "zh-CN": "回显示例" },
  "description": {
    "en-US": "Echo supplied text.",
    "zh-CN": "返回输入的文本。"
  },
  "compatibility": {
    "coginework": { "min": "2.4.0-beta.5", "max": "4.0.0" },
    "plugin_host_api": { "min": "1.1.0", "max": "2.0.0" }
  },
  "status": "active",
  "capabilities": ["tools"],
  "permissions": ["agent.tools.register"],
  "network": { "mode": "none", "domains": [] },
  "dependencies": [],
  "license": {
    "expression": "MIT",
    "path": "example-echo/LICENSE",
    "sha256": "REPLACE_WITH_ACTUAL_LICENSE_SHA256"
  },
  "published_at": "REPLACE_WITH_UTC_TIMESTAMP",
  "updated_at": "REPLACE_WITH_UTC_TIMESTAMP"
}

MIT 也是示例,必须与实际许可证一致。license.path 含包根 ID;在 macOS/Linux 可用 shasum -a 256 <LICENSE路径> 计算摘要,时间采用 YYYY-MM-DDTHH:MM:SSZ。

兼容区间与包清单保持一致;两处 dependencies 的区别见上节。网络访问要如实列出域名与 network.outbound,有前端时声明 frontend 能力和 ui.extend 权限。

第三步:准备展示条目

在 official-assets/presentation/v2/source.json 的 assets 添加下面的条目,分类必须在同一文件的 categories 中存在。更新时身份中的版本也要更新;由发布器生成 v1/v2 输出,不手工修改生成文件:

json
{
  "kind": "plugin",
  "id": "example-echo",
  "version": "1.0.0",
  "featured": false,
  "featured_order": 0,
  "category_ids": ["getting-started"],
  "icon": "puzzle",
  "details": {
    "en-US": "## Use\nEcho supplied text.\n\n## After adding\nCheck the plugin is loaded, then invoke example_echo.",
    "zh-CN": "## 适用场合\n返回输入文本。\n\n## 添加之后\n确认插件已加载,再调用 example_echo。"
  }
}

featured_order 即使不精选也必须填写。不要仅写“提供强大能力”;写清使用入口、完成的任务、所需配置和数据去向。展示字段不能更改安装权限或替代签名。新增场景分类、图标等以仓库合同为准,不猜枚举值。

第四步:校验并交接

有源码访问权限时,使用仓库开发 Python 环境,从根目录执行规范化。先将示例路径替换为真实 ID/版本:

bash
PYTHONPATH=src:. python - <<'PY'
import json
from pathlib import Path
from scripts.official_assets.contract import canonical_json_bytes, pretty_json_bytes

manifest = Path("official-assets/v1/packages/plugin/example-echo/1.0.0/example-echo/plugin.json")
manifest.write_bytes(canonical_json_bytes(json.loads(manifest.read_bytes())))
publication = Path("official-assets/v1/publication.json")
source = json.loads(publication.read_bytes())
source["assets"].sort(key=lambda item: (item["kind"], item["id"], item["version"]))
publication.write_bytes(pretty_json_bytes(source))
PY
PYTHONPATH=src:. python -m pytest \
  tests/contract/official_assets/test_production_source.py \
  tests/unit/official_assets/test_generate_presentation.py -q

新开发环境可按仓库贡献说明创建隔离虚拟环境并安装 .[dev,test];不要为做校验而修改用户已安装客户端。缺依赖、没有源码或测试失败时说明具体命令与错误,不宣称校验成功。

本地校验使用隔离测试密钥验证真实内容,不接触生产私钥、不上传。它不能证明生产目录代次或桌面兼容性。普通作者提交包、安装条目、展示条目与业务验收证据即可;维护者负责从生产已签名目录取 predecessor、推进 generation、审核并发布。没有生产上下文时不要猜 generation。

仓库维护者的完整操作说明是 docs/2026-09-21-plugin-publishing-handbook-v1.md,它包含环境核对、生产目录验签、首次初始化和发布读回。该路径只对有源码访问权限的维护者适用;QA 安装包或官网无需能打开它才能解释本页流程。

交接时输出这份清单:

text
结果:包已准备 / 内容 PR 待审 / 生产已发布(只能填写有证据的阶段)
插件:ID、版本、源码提交与运行包位置
文件:包、安装条目、展示条目
兼容:目标安装包、平台、Host API/UI SDK;已测和未测范围
校验:命令、结果、日志路径;业务任务复现步骤
权限:文件、网络域名、凭据、进程行为及必要配置
交付:PR URL 或交付目录;缺失输入与下一位负责人

更新、撤回与常见问题

新增插件要重装客户端吗? 在已验收的宿主能力范围内不需要。用户刷新市场、确认添加或更新即可;新宿主 API 或新的 UI SDK 主版本仍可能要求客户端升级。

插件改了代码怎么发? 升级插件 SemVer,新增版本目录,保留历史包和条目,更新展示版本。不能覆盖同版本字节。维护者发布新的 Catalog generation。

只改文案要升插件版本吗? 仅修改展示源中的分类、精选、图标、详情时不需要;仍须审核并运行内容发布流程。包清单或代码变化不能伪装成文案更新。

合并 PR 就上架了吗? 没有。维护者还要执行签名发布和公开读回;能下载也不等于在目标桌面完成业务验收。

发现已发布版本有问题怎么办? 提交撤回原因和受影响版本,由维护者把条目设为 revoked 并发布更高 generation。修复版本使用新的插件版本号;不要删除历史包、倒退目录或删除用户配置。撤回不等于强制卸载所有用户的现有插件。

QA 回答“文档里有,所以客户端一定支持”对吗? 不对。先确认客户端版本和实际功能,再区分文档描述、源码支持、生产上架、目标桌面验收四个事实。拿不到证据时说明缺口。

相关使用说明:插件、开发频道插件、安全与审批。